Richfaces: changing a component's 'rendered' attribute value with a4j:support in extendedDataTable

Wen Ping picture Wen Ping · Oct 25, 2010 · Viewed 8.8k times · Source

I'm trying to use richfaces extendedDataTable with a4j:support to change a rich:panel's 'rendered' attribute's value but it's not working.

This is part of my JSF page that contains a rich:extendedDataTable and a rich:panel:

<h:form id="tabForm">
<rich:extendedDataTable id="myTable" width="500px" height="250px"
value="#{extDataTableBean.extList}" var="dataRow"
selection="#{extDataTableBean.selection}" selectionMode="single">
    <rich:column>
        <f:facet name="header"><h:outputText value="ID" /></f:facet>
        <h:outputText value="#{dataRow.id}"></h:outputText>
    </rich:column>
    <rich:column>
        <f:facet name="header"><h:outputText value="Name" /></f:facet>
        <h:outputText value="#{dataRow.name}"></h:outputText>
    </rich:column>
    <a4j:support id="myTableTakeSelection" action="#{extDataTableBean.takeSelection}" event="onselectionchange" reRender="pane" />
</rich:extendedDataTable>
</h:form>
<rich:panel id="pane" rendered="#{extDataTableBean.showPane}">
<h:form id="secForm">
    <h:outputText value="ID : " />
    <h:inputText id="inTextID"  value="#{extDataTableBean.idFd}" />
    <br/>
    <h:outputText value="Name : " />
    <h:inputText id="inTextName" value="#{extDataTableBean.nameFd}" />
</h:form>
</rich:panel>

The default value of rich:panel 'rendered' attribute is false (set in the backing bean). What I wanted to achieve is when a row in the extendedDataTable is selected, its value is changed to true so that it is visible in GUI.

And this is part of my backing bean:

/* Constructor */
public ExtDataTableBean(){
    setShowPane(false); // default to false
    loadDataList();
}

/* Load some test data into extendedDataTable */
public void loadDataList(){
    extList = new ArrayList<MyData>();
    MyData e1 = new MyData();
    e1.setId(1);
    e1.setName("name 1");
    extList.add(e1);
    MyData e2 = new MyData();
    e2.setId(2);
    e2.setName("name 2");
    extList.add(e2);
}

public String takeSelection(){
    Iterator iterator = getSelection().getKeys();
    Object key = null;
    while(iterator.hasNext()){
        key = iterator.next();
    }
    /* set the values of inputText with value from selected row */
    setIdFd(extList.get(Integer.parseInt(key.toString())).getId());
    setNameFd(extList.get(Integer.parseInt(key.toString())).getName());
    setShowPane(true);
    return null;
}

public List<MyData> getExtList() {
            /* Lazy loading */
    if(extList == null){
        loadDataList();
    }
    return extList;
}

In the takeSelection( ) method I have setShowPane(true) to change the value of rich:panel 'rendered' attribute to true. The problem is rich:panel is not visible in the GUI when a row is selected.

I did another simple test by adding a h:commandButton with a4j:support to set showPane to true, like this:

<h:commandButton id="cmdBtn" value="Show Pane">
    <a4j:support id="cmdBtnSupport" reRender="pane" action="#{extDataTableBean.dispPane}" event="onclick" />
</h:commandButton>

and in the backing bean:

public String dispPane(){
    setShowPane(true);
    return null;
}

and it is working as expected. rich:panel is visible in GUI after the button is clicked.

What did I miss in my code?

Answer

Wen Ping picture Wen Ping · Oct 26, 2010

I think I found the cause of the problem from this website: http://community.jboss.org/wiki/CommonAjaxRequestsProblems#conditionalRendering

An extract on the part that described the problem:

Client Side updates:

reRender attribute should not be pointed to conditionally rendered elements, because the framework has no idea where to add the element which wasn't in DOM before. Parents of such components should be reRendered instead.

So, after I modified the part to be rerendered and rendered binding to as follow then it is working now:

<rich:panel id="pane" >
    <h:form id="secForm" rendered="#{extDataTableBean.showPane}" >
        <h:outputText value="ID : " />
        <h:inputText id="inTextID"  value="#{extDataTableBean.idFd}" />
        <br/>
        <h:outputText value="Name : " />
        <h:inputText id="inTextName" value="#{extDataTableBean.nameFd}" />
    </h:form>
</rich:panel>