JSF 2/Primefaces p:ajax not updating panel after onchange event is fired

jsf-2primefaces

I am really stuck with this for the last 2 days and am struggling to understand how Primefaces updates UI components on the client based on their ID.

I have a h:selectOneMenu with a count for the number of panels to be displayed. Each p:panel will contain a panelGrid with numerous form elements. The onchange event on the drop down is fired and I can see the count in the Managed Bean. I do not see panels increasing dynamically on the client side though.i think something is wrong with my p:ajax params, but I don;t fully understand how it works. here is the relevant code:

    <h:selectOneMenu id="numapps" value="#{mbean.appCount}">
                <f:selectItem itemLabel="1" itemValue="1" />
                <f:selectItem itemLabel="2" itemValue="2" />
                <f:selectItem itemLabel="3" itemValue="3" />
                <f:selectItem itemLabel="4" itemValue="4" />
                <f:selectItem itemLabel="5" itemValue="5" />
                <p:ajax update="appsContainer" event="change"   
                    listener="#{mbean.onChangeNumApps()}" />    
    </h:selectOneMenu>

    <p:panel id="appsContainer" >
           <p:panel header="Application" id="appsPane" value="#{mbean.submittedApps}" var="app" multiple="true">

submittedApps is a List containing the panel form elements. Here is my mbean listener:

public void onChangeNumApps()
{
    List<Apps> c = new ArrayList<Apps>();
    logger.info("on change event fired");
    logger.info("new value is "+mbean.getAppCount());
    for (int i=0;i < mbean.getAppCount();i++)
    {
        c.add(new App());
    }
    mbean.setSubmittedApps(c);
}

I am mixing p:ajax with h:selectone because i could not get p:selectone working for some reason – possibly due to a CSS collision with my stylesheet??

Best Answer

Adding/Removing dynamic component from the JSF tree is lot simpler. Although I work majorly on RF and JSF2.0, so I won't be able to help you much in terms of code for primefaces but I can list down the steps which can be followed to add dynamic components based on the number received from the valuechange listener.

In your post you need to have dynamic number of form elements based on the value submitted from the

For this on valuechanelistener you can fetch the value of the number of the panels selected.

  1. You create a new Panel in the valuechangelistener.
  2. Create desired form elements based on the number received from valuechangelistener.
  3. Add these elements as a child to the panel.
  4. Add this panel as a child to the panel which is present on the page previously.

Instead of manually assigning ID to each dynamic component you can use the JSF inbuilt uniqueID function which will automatically provide you with unique ID's. In case you need to further use the dynamic components for extarcting values then you need to store the ID's in a separate collection and based on the ID you can then fetch the value of the dynamic component.

To get unique ID for component:-

FacesContext.getCurrentInstance().getViewRoot().createUniqueId();

To dynamically add a component to the JSF tree please find the code snippet mentioned below:-

HtmlPanelGrid panelGrid=new HtmlPanelGrid();
panelGrid.setColumns(2);
String uniqueId=FacesContext.getCurrentInstance().getViewRoot().createUniqueId();
panelGrid.setId(uniqueId);    arrLstComponentIds.add(uniqueId);
HtmlInputText inputText = new HtmlInputText();    
HtmlOutputLabel outputLabel=new HtmlOutputLabel();
                                          panelGrid.getChildren().add(outputLabel);
panelGrid.getChildren().add(inputText);
htmlGridElement = new HtmlPanelGrid();      htmlGridElement.getChildren().add(panelGrid); 

You need to rerender your panel so that the changes in the JSF tree are reflected.

Related Topic