tags:

views:

91

answers:

2

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?

Thanks in advanced for any help.

A: 

<rich:extendedDataTable> is Ajax-enabled out of the box. No need to add the <a4j:support> tag, which is intended to bring ajax functionality to non-ajax JSF components, such as <h:inputText>.

So, try this instead:

<rich:extendedDataTable onselectionchange="#{extDataTableBean.takeSelection}">

Good luck.

Markos Fragkakis
Thanks for your answer Markos, but I get a ServletException if I changed my code to use <rich:extendedDataTable onselectionchange="#{extDataTableBean.takeSelection}">, I think maybe 'onselectionchange' attribute is for client side script method call (javascript).
Wen Ping
A: 

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 & 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>

Hope this is the correct solution. If you know there is a better or correct way to do it please do let me know.

Thanks for helping.

(OT: I'm new to stackoverflow, what should I do next for this question I raised? Should I close it or I need to do something else? Or I need to wait for someone else to do it for me?)

Wen Ping
Wen, you can also leave the <rich:panel> as is (with the rendered attribute), just include it in a <h:panelGroup>, and rerender the <h:panelGroup> instead. The panel group will render a div I think, and in case the <rich:panel> rendered evaluates to false, no harm done, the panelGroup will have rendered in order to be reRendered afterwards.
Markos Fragkakis
Don't close the question, if you are satisfied with your answer, check it as the correct answer for the question.
Markos Fragkakis
You are right Markos. I guess as long as the component with rendered binding is enclosed within another component to be rerendered then it will work. I will check this as the correct answer as you have suggested. Thank you for your help.
Wen Ping