2

我想实现类似于http://www.primefaces.org/showcase/ui/pprSelect.jsf但我需要一个双组合的集合,所以我将它包装在ui:repeat

我需要在后端检查双重组合集合中的哪个元素已更改以及我需要重新加载什么。在示例中使用 p:ajax 进行通信,但 AjaxBehaviorEvent 没有给我任何元素索引的想法(我的意思是由 ui:repeat 生成的双组合元素的索引)

我的客户端代码,想法是每次引发 ajax 事件时更新bean:selectedIndex (更改selectOneMenu的值),并且bean:selectedIndex的值将设置为更改的selectOneMenu的索引

private List<State> productStates
private int selectedIndex;
private List<Group> groups;
private Map<Integer, Collection<Device>> availableDevicesMap;
<ui:repeat var="state" value="#{bean.productStates}" varStatus="iter">

    <p:selectOneMenu id="devGroup" value="#{state.group}">  
        <f:selectItems value="#{bean.groups}"  />  
            <p:ajax  update="refreshable"  process="devGroup, @this"  listener="#{bean.refreshDevicesForState}" >
                    <f:setPropertyActionListener target="#{bean.selectedIndex}" value="#{iter.index}"/>
            </p:ajax>                                    
    </p:selectOneMenu>

    <!-- THIS WILL BE UPDATED -->
    <h:panelGroup id="refreshable">
            <p:selectManyButton  id="devices" value="#{state.devices}" >  
                <f:selectItems value="#{bean.availableDevicesMap[status.index]}"   />  
            </p:selectManyButton> 
    </h:panelGroup>
</ui:repeat>

后端无法按预期工作。未调用setPropertyActionListenerselectOneMenu组件未将选定组作为值

public refreshDevicesForState(AjaxBehaviorEvent e) {
        SelectOneMenu menu = (SelectOneMenu)e.getComponent();
    // this value is not as selected on frontend
        Group group = (Group)menu.getValue();

    // selectedIndex will not be set, so I assume that setPropertyActionListener didn't invoked
    availableDevicesMap.put(selectedIndex, group.getDevices());
}

我也尝试了下面的代码,但我认为它很难看

// id will be grandpaId:parentId:index:myId 
String selectedIndex = IdHelper.getIdPart(e.getComponent().getClientId(), -2);
State state = productStates.get(Integer.parseInt(selectedIndex));

我在 glassfish 和 Mojarra 上使用最新的 primefaces 作为 jsf 参考实现

感谢您的任何帮助

在更一般的意义上:

我有支持 bean 上的对象列表,比如说 Cars

List<Car> cars

在前端我迭代它们并为每辆车创建选择品牌选择模型组合。当用户为第四辆车选择品牌时,我想在后端了解第四辆车将被更改,我将重新加载这辆车的可用型号列表

 <ui:repeat var="state" value="#{bean.cars}" >
    <p:selectOneMenu id="brands"/>// select brand

    <p:selectOneMenu "models"/>// show available models depends on selected brand
 </ui:repeat>

如何在 JSF 世界中正确处理它?

4

1 回答 1

2

我的第一个建议是对 Group 使用转换器。SelectOneMenu 不能设置自定义类,只能在转换器的帮助下。(一个例子是在自动完成:http: //www.primefaces.org/showcase/ui/autoCompletePojo.jsf

其次,在您的 bean 处理程序中,productStates变量已经包含(selectOneMenus 的)选定值。您可以更轻松地使用它,而不是从事件中访问它。

如果 selectOneMenus 的值取决于 State,则必须修改:

<f:selectItems value="#{bean.groups}"  />

能够表达应该显示哪些组值。

如果你想调试它(没有eclipse调试),你可以使用消息,例如:

将此添加到 xhtml:

<p:growl id="msgs" showDetail="true"/>

在 bean 中:

public refreshDevicesForState(AjaxBehaviorEvent e) {

 ...
 FacesMessage msg = new FacesMessage("Selected", "any debug info" + productStates.get(0).getGroup());  
 FacesContext.getCurrentInstance().addMessage(null, msg);  

}

根据您的模组,我修改了答案。我会这样做:

xhtml:

<ui:repeat var="state" value="#{bean.productStates}" varStatus="iter">

 <p:selectOneMenu id="devGroup#{iter.index}" value="#{state.group}"
        valueChangeListener="#{bean.updateSubProperty}" immediate="true">  
  <f:selectItems value="#{bean.groups}"  />  
  <f:attribute name="index" value="#{iter.index}" />
 </p:selectOneMenu>

 <p:selectOneMenu id="subDevGroup#{iter.index}">
  ...
 </p:selectOneMenu>
</ui:repeat>

豆:

 public void updateSubProperty(ValueChangeEvent vce) {
  String index = vce.getComponent().getAttributes().get("index").toString();
  int i = Integer.parseInt(index); //this is the index of the selected selectOneMenu
  ///...

  //update sub selectOneMenu
  RequestContext.getCurrentInstance().update("subDevGroup" + index);
 }
于 2013-05-24T10:07:24.220 回答