动态重新加载选择多个组件中的项目

时间:2013-05-23 16:27:11

标签: jsf jsf-2 primefaces

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

我需要在后端检查来自双组合集合的哪个元素被更改以及我需要重新加载的内容。对于通信使用p:ajax,如例子中所示,但是AjaxBehaviorEvent不会让我对元素的索引有任何想法(我的意思是由ui生成的双组合元素的索引:重复)

我的客户端代码,每次引发ajax事件时都会更新 bean:s​​electedIndex (更改值为 selectOneMenu ),值为 bean:s​​electedIndex 将被设置为已更改的 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>

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

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的对象列表,比如说汽车

List<Car> cars

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

 <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世界中正确处理它?<​​/ p>

1 个答案:

答案 0 :(得分: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);  

}

我根据你的mod修改了我的答案。我会这样做:

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);
 }