"show more" <h:commandButton> with ajax

505 views Asked by At

I use JSF in implementation MyFaces 2.0. In my web application I want to have page with button "show more". User get page, there are only button and hide form with some information (e.g. with label). When user click this button he would see on the same page with showed label. When he click again label should hide.

myPage.xhtml:

<?xml version='1.0' encoding='UTF-8' ?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:f="http://java.sun.com/jsf/core">

<h:head>
</h:head>

<h:body>
    <h:form>
       <h:commandButton value="show more" action="#{bean.showOrHide}">
           <f:ajax render=":formWithLabel"/>
       </h:commandButton>
    </h:form>  
    <hr/>

    <h:form id="formWithLabel" rendered="#{bean.show}">
       <h:outputLabel value="More information"/>
    </h:form>
</h:body>

Bean.java:

@ManagedBean
@ViewScoped
public class Bean {

  private boolean show;

  //getters, setters

  public void showOrHide(){
    show = !show;
  }
}

This code seems to be not working. What is wrong?

1

There are 1 answers

0
BalusC On BEST ANSWER

Indeed, this approach won't work.

The <f:ajax render=":formWithLabel"/> works basically as follows:

  1. JavaScript sends an ajax request.
  2. JSF returns an ajax response with <update id="formWithLabel"> with therin the updated HTML.
  3. JavaScript uses document.getElementById("formWithLabel") to find the element so that its inner HTML content can be replaced with the one from ajax response.

However, as the <h:form id="formWithLabel" rendered="#{bean.show}"> is never rendered in first place, JavaScript can't find anything in HTML document to replace the inner HTML content with the one from ajax response and fails silently.

You need to wrap it in another JSF component which is always rendered to HTML output, so that JavaScript can find it while it needs to update the HTML document based on ajax response.

<h:form>
   <h:commandButton value="show more" action="#{bean.showOrHide}">
       <f:ajax render=":groupWithLabel"/>
   </h:commandButton>
</h:form>  

<h:panelGroup id="groupWithLabel">
    <h:form id="formWithLabel" rendered="#{bean.show}">
       <h:outputLabel value="More information"/>
    </h:form>
</h:panelGroup>

See also:


Unrelated to the concrete problem, you may stumble upon a new problem when you intend to invoke actions on this form. You might want to swap the <h:panelGroup> with the <h:form>.

See also: