2

I am developing application with JSF 2.0 and Primefaces 3.2, I am running into the following problem: ActionListeners not invoked if the content is loaded dynamically with ajax request.

Main layout:

<div id="content">
    <h:form name="content_form" id="content_form">
        <ui:insert name="content" />
    </h:form>
</div>

Index page (contents are loaded dynamically based on menu actions):

<ui:composition template="layout.xhtml">
    <ui:define name="content">
        <ui:include src="#{ajaxViewBean.viewName}" /> 
    </ui:define>
</ui:composition>

Menu actions is generated as follows:

        FacesContext context = FacesContext.getCurrentInstance();
        MethodExpression methodExpression = context
                .getApplication()
                .getExpressionFactory()
                .createMethodExpression(
                        context.getELContext(),
                        "#{ajaxViewBean.setViewName('" + navItem.getUrl()
                                + "')}", null,
                        new Class[] { ActionEvent.class });
        displayMenuItem.setUpdate(":content_form");
        displayMenuItem
                .addActionListener(new MethodExpressionActionListener(
                        methodExpression));

Upon clicking menu items it call AjaxViewBean "Request scope" to set the current view page and update the "content_form" in the main layout

Included Pages (in which action listener not working)

  • First Try - File Upload (uploadFile.xhtml)

    <h:body>
    <h:form enctype="multipart/form-data">
    
        <p:fileUpload fileUploadListener="#{fileUploadController.handleFileUpload}"  
                      mode="advanced"  
                      update="messages"   
                      multiple="true"  
                      sizeLimit="100000"   
                      allowTypes="/(\.|\/)(gif|jpe?g|png)$/"/>  
    
        <p:growl id="messages" showDetail="true"/>  
    </h:form>
    

    fileUploadController is never invoked. If I requested the uploadfile.xhtml directly, or included it on the first load, I can upload the file so I am sure that upload is working file and everything is configured correctly in web.xml.

  • Second Try - Menu action listener in the include page

    <h:body>
    <h:form>
        <p:menu type="tiered" style="width:180px">
            <p:submenu label="Ajax Menuitems" icon="ui-icon-refresh">
                <p:menuitem value="Save"
                    actionListener="#{ajaxViewBean.setViewName()}" update="messages"
                    icon="ui-icon-disk" />
                <p:menuitem value="Update" actionListener="#{buttonBean.update}"
                    update="messages" icon="ui-icon-arrowrefresh-1-w" />
            </p:submenu>
        </p:menu>
    </h:form>
    

    Also the event in action listener is never firing, although it's firing in the main page with is generated dynamically from the code mentioned above

Maven Dependencies:

<dependency>
    <groupId>com.sun.faces</groupId>
    <artifactId>jsf-api</artifactId>
    <version>2.1.4</version>
</dependency>
<dependency>
    <groupId>com.sun.faces</groupId>
    <artifactId>jsf-impl</artifactId>
    <version>2.1.4</version>
</dependency>
<dependency>
    <groupId>javax.servlet.jsp.jstl</groupId>
    <artifactId>jstl-api</artifactId>
    <version>1.2</version>
</dependency>
<dependency>
    <groupId>com.sun.facelets</groupId>
    <artifactId>jsf-facelets</artifactId>
    <version>1.1.14</version>
</dependency>
<dependency>
    <groupId>javax.el</groupId>
    <artifactId>el-api</artifactId>
    <version>2.2</version>
</dependency>
<dependency>
    <groupId>org.glassfish.web</groupId>
    <artifactId>el-impl</artifactId>
    <version>2.2</version>
</dependency>
<dependency>
    <groupId>org.primefaces</groupId>
    <artifactId>primefaces</artifactId>
    <version>3.2</version>
</dependency>
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.2.2</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.3</version>
</dependency>  

Can someone please advice if I am missing something, or how can I solve this ?

Actually this is my first post in Stackoverflow, so I hope that I made myself clear and the format is not messed up

2 Answers2

2

Fixed!, and I am posting the answer (maybe can be useful for someone) Steps as follows:

Something to highlight:

  • Globally disabling the partial state saving has however the disadvantage that the view state size will grow in size. So if you're using server side state saving method, then the server's memory usage will increase, or if you're using client side state saving method, then the network bandwidth usage will increase. Basically, you get the same view state information as it was in JSF 1.x. If possible, you can also just disable the partial state saving on a per-view basis by the following context parameter in web.xml
Community
  • 1
  • 1
1

As I can see you are nesting forms. This is not allowed in HTML/XHTML.

You have the enclosing content_form and the include pages also have a form each.

Try removing the content_form:

<div id="content">
    <ui:insert name="content" />
</div>

and change the displayMenuItem to set the update to content div:

displayMenuItem.setUpdate(":content");

I hope it helps.

rbento
  • 9,919
  • 3
  • 61
  • 61
  • Thanks a lot for answering my question, it's true I was nesting the forms in the example, and I have fixed this in my code and not working. I followed this URL: http://stackoverflow.com/questions/2118656/hcommandlink-hcommandbutton-is-not-being-invoked/2120183#2120183 and made sure that nothing is being violated in these rule. Regarding the provided solution, I applied it and I received "Cannot find component with identifier ":content" in view." In my new code, I made sure that it's no forms nested, so I placed in the index page before the included page and it wasn't rendered – Khaled Nabil Ibrahim May 16 '12 at 09:39