Search code examples
jsf-2icefaces-3

Is there a way to intercept a ExpansionToggle valueChange event before the client toggles the component?


I am using the 3.3 version of IceFaces and we have a data table of people. We need an expansion button that allows the user to update any attributes of a person in the data table. The tag, ace:expansionToggle is the one I think can be used, but if I catch events with a changeListener, the client has already toggled the component. I need to validate all fields in that panel so that if validation fails, the panelExpansion component won't close. Here's some code to describe what it is I'm trying to do. Binding the component to the backing bean seemed like a good idea but if I set a breakpoint in the getter and setter of expansionToggle, the client has already collapsed the panel before I can do anything about it.

<ace:dataTable id="driverListTable" value="#{persons}" var="person">
    <ace:column id="exp">
        <ace:expansionToggler 
            binding="#{personBean.expansionToggle}" 
            changeListener="#{directDriverInfoBean.handleToggleEvent}"/>
    </ace:column>

    <ace:column headerText="#{msg.label_driver}">
        <ice:outputText value="#{person.firstName} #{person.lastName}"/>
    </ace:column>

    <ace:column styleClass="dobColWidth" headerText="#{msg.label_dob}">
        <ice:outputText value="#{person.userDob}"/>
    </ace:column>

    <ace:column styleClass="driverColWidth" headerText="Marital Status">
        <ice:outputText value="#{person.maritalStatus}"/>
    </ace:column>

    <ace:column headerText="Person Status">
        <ice:outputText value="#{person.status}"/>
    </ace:column>

    <ace:panelExpansion>
        <show all fields for person here>
    </ace:panelExpansion>
<ace:dataTable>

What options do I have here?

Thanks, Patrick


Solution

  • I just found out about the attribute 'stateMap'. It allows you access to each row in the dataTable. So what you could do is when they click the row, in your 'handleToggleEvent' method you know what row they clicked on. You could do your validation and if it fails, you can check your stateMap for the row and force it to be setExpanded(false)...

    //add stateMap attribute to ace:dataTable
    
    <ace:dataTable id="driverListTable" value="#{persons}" var="person" stateMap="stateMap">
    
    //added the attribute currentRow so you can access row object.
    
     <ace:column id="exp">
        <ace:expansionToggler 
            binding="#{personBean.expansionToggle}" 
            changeListener="#{directDriverInfoBean.handleToggleEvent}">
            <f:attribute name="currentRow" value="#{person}" />
            <ace:expansionToggler>
       </ace:column>
    
    //add the following variable to your backing bean
    
    /** This row state map object allows us access to all the rows in the data table. */
       private RowStateMap stateMap = new RowStateMap();
    
    // edit your handleToggleEvent() method like the following:
    
      public void handleToggleEvent(ExpansionChangeEvent event){
          RowObject obj = event.getComponent().getAttributes().get("currentRow");//one way to know what row they clicked.
    
          //do your validation
    
          if(failed){
    
           /*find the row in the state map.*/
           RowState rs = (RowState) stateMap.get(obj); 
    
           /*force it to not be expanded*/
           rs.setExpanded(false);
          }
    

    }

    hope this works!