How to render a p:panel, triggered from the choice of a p:selectonemenu?

Spyridon Non Serviam picture Spyridon Non Serviam · Apr 1, 2013 · Viewed 9.5k times · Source

I am using Primefaces 3.4 and JSF 2.1 and I am trying to have a p:panel item appear and dissapear regarding the choices of p:oneselectmenu. I have a p:datatable inside the panel that I want to appear and be populated dynamically and that is why I am using the panel. The datatable thing works well but the panel no. I tried linking the "rendered" option on the panel with a variable that changes with the change of every selection of the menu but nothing happened. I also tried it with an p:outputpanel but nothing happened. So I tried using a button with the same actions but again it failed. This is my code:

<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:p="http://primefaces.org/ui"
  xmlns:f="http://java.sun.com/jsf/core">
<h:body>
    <ui:composition template="/template.xhtml">
        <ui:define name="title">
            #{msg.teaching}: #{msg.socialSecurity}
        </ui:define>
        <ui:define name="body">
            <h:form id="form">
                <p:messages id="messages" autoUpdate="true"/>                  
                <p:panel id="selectSocialSecurityPanel" rendered="true">
                    <p:panelGrid>
                        <p:row>
                            <p:column>
                                <p:selectOneMenu value="#{selectOneMenuSocialSecurityTeachingBean.choice}">
                                    <p:ajax update="socialSecurityDataTablePanel, socialSecurityDataTable, toUpdate" listener="#{dataTableSocialSecurityBean.updateTable()}"/>
                                    <f:selectItem itemLabel="#{msg.select}" itemValue=""/>
                                    <f:selectItems value="#{selectOneMenuSocialSecurityTeachingBean.socialSecurityTeachingList}"/>
                                </p:selectOneMenu>
                            </p:column>
                            <p:column>
                                <p:commandButton value="#{msg.find}" actionListener="#{dataTableSocialSecurityBean.updateTable()}" update="socialSecurityDataTablePanel, socialSecurityDataTable, toUpdate" id="button">
                                    <f:ajax render="toUpdate"/>
                                </p:commandButton>
                            </p:column>
                        </p:row>
                    </p:panelGrid>
                </p:panel>                    
                <p:outputPanel id="toUpdate" rendered="#{dataTableSocialSecurityBean.rendered}" autoUpdate="true">
                    <p:panel id="socialSecurityDataTablePanel">
                        <p:dataTable id="socialSecurityDataTable" var="unit" value="#{dataTableSocialSecurityBean.socialSecurityList}">                    
                            <p:columns value="#{dataTableSocialSecurityBean.columns}" var="column" columnIndexVar="colIndex">
                                <f:facet name="header">
                                    #{column.header}
                                </f:facet>
                                #{unit[column.property]}
                            </p:columns>
                        </p:dataTable>                       
                    </p:panel>
                </p:outputPanel>
            </h:form>
        </ui:define>
    </ui:composition>
</h:body>

and this:

@ManagedBean
@ViewScoped
public final class DataTableSocialSecurityBean implements Serializable {

    private String choice;
    private List<Unit> socialSecurityList;
    private boolean rendered;
    private List<ColumnModel> columns = new ArrayList<ColumnModel>();

    public boolean getRendered(){
        System.out.println("DataTableSocialSecurityBean getRendered");
        System.out.println("DataTableSocialSecurityBean getRendered="+rendered);
        return rendered;
    }

    public void updateTable() {
        rendered=true;
        socialSecurityList = new ArrayList<Unit>();
        createDynamicColumns();
        populateDataTable(socialSecurityList);

    }
}

Any ideas?

Answer

partlov picture partlov · Apr 1, 2013

Your rendered field is initially false so panel is not rendered on first view. In that view on initial HTML there is not tag with id toUpdate so it can't be rendered. I suggest you to put this panel inside some h:panelGroup and rerender this component:

<h:panelGroup id="myContainer" layout="block">
  <p:outputPanel id="toUpdate" rendered="#{dataTableSocialSecurityBean.rendered}" autoUpdate="true">
  </p:outputPanel>
</h:panelGroup>

and you use render="myContainer". I would also suggest you to use p:ajax instead of f:ajax for primefaces components.

You can try adding effect adding p:effect component as child of p:outputPanel:

<p:effect type="explode" event="load"/>

For a full list of events see PrimeFaces Users Guide.