2015-11-09 2 views
0

Это является продолжением до: How can I create a JSF composite component that binds a Collection to both an h:selectOneMenu and h:selectManyListbox?Как добавить функцию f: ajax к моему составному компоненту, который привязывает коллекцию к h: selectOneMenu и h: selectManyListbox?

У меня есть составной компонент, который позволяет пользователю переключаться между ч: selectOneMenu и ч: selectManyListbox и возвращает коллекцию в качестве «выбранного» значения. Это отлично работает. Теперь я пытаюсь добавить к нему поддержку ajax, так что, если значение выбрано в меню или списке, запускается событие ajax (это означает, что mySelected должен иметь свое значение, и я могу повторно отобразить любой другой компонент на страница Я хочу

<swr:singleMultiSelect list="#{myBean.myList}" 
         selected="#{myBean.mySelected}" 
         singleSelect="#{myBean.singleSelect}"> 
    <f:ajax event="valueChange" execute="@this" 
      render="buttonPanel"/> 
</swr:singleMultiSelect> 

со следующим атрибутом в моем составного компонента:.

<cc:clientBehavior name="valueChange" event="valueChange" 
        targets="selectOneMenu selectManyListbox"/> 

Я возникли проблемы заполнения mySelected с величиной selectOneMenu Когда я делаю не-. ajax form submit, processUpdates позаботится об этом ... Я не совсем уверен, как это сделать то же самое для события ajax.

Вот мой композитный код компонента:

singleMultiSelect.xhtml

<?xml version="1.0" encoding="US-ASCII"?> 
<!DOCTYPE html> 
<ui:composition 
    xmlns:f="http://xmlns.jcp.org/jsf/core" 
    xmlns:h="http://xmlns.jcp.org/jsf/html" 
    xmlns:ui="http://java.sun.com/jsf/facelets" 
    xmlns:cc="http://java.sun.com/jsf/composite" 
    xmlns:c="http://java.sun.com/jstl/core" 
    xmlns:ace="http://www.icefaces.org/icefaces/components" 
    > 

    <cc:interface componentType="singleMultiSelect"> 

     <!-- The initial list of objects --> 
     <cc:attribute name="list" type="java.util.List" required="true"/> 
     <!-- The selected objects --> 
     <cc:attribute name="selected" type="java.util.Collection" required="true"/> 
     <!-- whether to display the selectOneMenu (true) or selectManyBox (false) --> 
     <cc:attribute name="singleSelect" type="java.lang.Boolean" 
        required="false" default="true"/> 
     <cc:clientBehavior name="valueChange" event="valueChange" 
         targets="selectOneMenu selectManyListbox"/> 

    </cc:interface> 
    <cc:implementation> 

     <span id="#{cc.clientId}"> 

      <ace:checkboxButton id="singleSelectChkBx" 
           value="#{cc.attrs.singleSelect}"> 
       <ace:ajax render="#{cc.clientId}"/> 
      </ace:checkboxButton>      

      <h:selectOneMenu id="selectOneMenu" 
          rendered="#{cc.attrs.singleSelect}" 
          binding="#{cc.singleSelected}">      
       <f:selectItems value="#{cc.attrs.list}"/> 
      </h:selectOneMenu> 

      <h:selectManyListbox id="selectManyListbox" 
           rendered="#{! cc.attrs.singleSelect}" 
           value="#{cc.attrs.selected}"> 
       <f:selectItems value="#{cc.attrs.list}"/> 
      </h:selectManyListbox> 

     </span> 

    </cc:implementation> 
</ui:composition> 

SingleMultiSelect.java

public class SingleMultiSelect extends UINamingContainer { 

    private UISelectOne singleSelected; 

    public SingleMultiSelect() { 
     super(); 
    } 

    @Override 
    public void processUpdates(FacesContext context) { 
     super.processUpdates(context); 

     if (getAttributes().get("singleSelect") == Boolean.TRUE) { 
      HashSet selected = new HashSet(); 
      if(singleSelected.getValue() != null) { 
       selected.add(singleSelected.getValue()); 
      } 
      getValueExpression("selected").setValue(context.getELContext(), selected); 
     } 
    } 

    @Override 
    public void encodeBegin(FacesContext context) throws IOException { 
     if (getAttributes().get("singleSelect") == Boolean.TRUE) { 
      Collection selected = (Collection) getAttributes().get("selected"); 
      if (selected != null && !selected.isEmpty()) { 
       singleSelected.setValue(selected.iterator().next()); 
      } else { 
       singleSelected.setValue(null); 
      } 
     } 

     super.encodeBegin(context); 
    } 
    /** 
    * @return the singleSelected 
    */ 
    public UISelectOne getSingleSelected() { 
     return singleSelected; 
    } 

    /** 
    * @param singleSelected the singleSelected to set 
    */ 
    public void setSingleSelected(UISelectOne singleSelected) { 
     this.singleSelected = singleSelected; 
    } 
} 

ответ

0

Добавлена ​​Аякса тег в selectOneMenu с слушателя (связан с методом в FacesComponent), который обновляет выбранную коллекцию:

singleMultiSelect.xhtml:

<h:selectOneMenu id="selectOneMenu" 
       rendered="#{cc.attrs.singleSelect}" 
       binding="#{cc.singleSelected}">      
    <f:selectItems value="#{cc.attrs.list}"/> 
    <f:ajax event="valueChange" execute="@this" 
        listener="#{cc.updateSelected}"/> 
</h:selectOneMenu> 

SingleMultiSelect.java:

public void updateSelected(AjaxBehaviorEvent event) { 

    FacesContext context = FacesContext.getCurrentInstance(); 

    if (getAttributes().get("singleSelect") == Boolean.TRUE) { 
     HashSet selected = new HashSet(); 
     if(singleSelected.getValue() != null) { 
      selected.add(singleSelected.getValue()); 
     } 
     getValueExpression("selected").setValue(context.getELContext(), selected); 
    } 
}