Spyridon Non Serviam
Spyridon Non Serviam

Reputation: 387

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

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?

Upvotes: 2

Views: 10774

Answers (2)

partlov
partlov

Reputation: 14277

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.

Upvotes: 7

Serkan Arıkuşu
Serkan Arıkuşu

Reputation: 5619

For the rendered event to act like you want, the component should be visible (exist in the dom). The most known hack is to apply the rendered attribute to an inner component (not the outputpanel but the panel inside it)

<p:outputPanel id="toUpdate"  autoUpdate="true">
    <p:panel id="socialSecurityDataTablePanel" rendered="#{dataTableSocialSecurityBean.rendered}">
</p:panel>
</p:outputPanel>

This way, your outputPanel is visible everytime (exist in the DOM) and can tell its children to render themselves based on conditions.

Upvotes: 2

Related Questions