Ajax ReRendering – How to reRender part of your page in Myfaces using Richfaces

If you read this post I assume you have a general knowledge about what Ajax is, and what capabilities lies within. As a web-developer, there might be times where you would like to not do a full submit of your page, but you would actually like to just update a small part of the page. An application that achieves this gives the user a more “desktop-application”-like experience, and it will mostly also be a saver when it comes to performance, as you only load a part of the page – as well as the data going to be displayed in it.

For Myfaces, both 1.1 and 1.2 specification, there is a component library named RichFaces. The components there are nice to use for adding ajax-features to your application, and there are also possibilities of adding those capabilities to non-ajax components in myFaces or Tomahawk libraries.

You can download the libraries from here: RichFaces. Depending on the version of Myfaces you use, you need to get different RichFaces version. For MyFaces 1.1 core you need the RichFaces 3.1.X libraries, for Myfaces 1.2 core you can get the 3.2.X libaries. The 3.2.X libraries does NOT support Myfaces version 1.1

Then, to make use of the new library you need to add the following to your web.xml:

    <filter>
        <display-name>RichFaces Filter</display-name>
        <filter-name>richfaces</filter-name>
        <filter-class>org.ajax4jsf.Filter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>richfaces</filter-name>
        <servlet-name>Faces Servlet</servlet-name>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>INCLUDE</dispatcher>
    </filter-mapping>

On the top of your jsps you need to include the taglibraries by inserting these lines:
<%@ taglib uri=”http://richfaces.org/rich&#8221; prefix=”rich”%>
<%@ taglib uri=”https://ajax4jsf.dev.java.net/ajax&#8221; prefix=”a4j”%>

So, when it comes to the actual reRendering of components or part of your page, there are several different ways of doing this.

In its simplest form, you can use the a4j:support to add ajax capabilities to ordinary myfaces components. In this example we use it on an inputText. You set the event property (javascript events), give the id of the component(s) you want to reRender, and then you go. Everytime a user releases a key, the reRender will be called, and getting the outText component again:

<h:inputText id="myInput" value="#{myBean.myProperty}">
    <a4j:support event="onkeyup" reRender="outText"></a4j:support>
</h:inputText>

<h:outputText id="outText" value="#{myBean.myProperty}"></h:outputText>

If you use componentBindings, and create those components programmatically, you need to do your custom modification of that component in the setter-method of this component to let the reRendering work. Let’s say you have a panelGrid, and you create it java-side and add two outPutTexts to it. If the value of those outputTexts change, and you want to reRender the panelGrid to display this, then the setter of this component is invoked as long as the getter returns null. So you should do like this:

Jsp:

<h:inputText id="myInput" value="#{myBean.myProperty}">
    <a4j:support event="onkeyup" reRender="outPanel"></a4j:support>
</h:inputText>

<t:panelGrid id="outPanel" binding="#{myBean.htmlPanelGrid}"/>

Java:

public HtmlPanelGrid getHtmlPanelGrid()
{
    return htmlPanelGrid;
}

public void setHtmlPanelGrid(HtmlPanelGrid htmlPanelGrid)
{
    //Clean exisiting children
    htmlPanelGrid.getChildren().clear();

    //Add your modifications
    htmlPanelGrid.getChildren().add(createOutputText("out1","#{myBean.myProperty1}"));
    htmlPanelGrid.getChildren().add(createOutputText("out2","#{myBean.myProperty2}"));

    this.htmlPanelGrid = htmlPanelGrid;
}

private UIComponent createOutputText(String id, String valueBinding)
{
    HtmlOutputText out = new HtmlOutputText();
    out.setId(id);
    ValueBinding vb = FacesContext.getCurrentInstance().getApplication().createValueBinding(
    valueBinding);
    out.setValueBinding("value", vb);

    return out;
}

It is also possible to create the a4j:support programmatically, like this:

HtmlAjaxSupport ajaxSupport = new HtmlAjaxSupport();
ajaxSupport.setEvent("onchange");
ajaxSupport.setId("ajaxSupport");
ajaxSupport.setFocus("myForm:theIdOfComponentIWantToFocusOnAfterAjaxSubmit");
ajaxSupport.setReRender("myForm:idOFComponentIWantToReRender"); 

myUiComponent.getChildren().add(ajaxSupport);

There is also a component that creates a javascript-function for you which you can use to pass properties to your bean, execute actions and finally reRender components. It’s called a4j:jsFunction. Let’s say I have a h:commandButton, and when I click it I want to set a value to a property in my bean, I want to run an action, and then display the results. I could have done this with an t:updateActionListener, but then I would have been forced to do a full submit of the whole page. Instead, I can do it like this:


    //Define javascriptFunction with parameter
    <a4j:form>
        <a4j:jsFunction name="setParameterAndRerender" action="#{myBean.action}" reRender="outPanel" >
             <a4j:actionparam name="param1" assignTo="#{myBean.myProperty1}"  />
         </a4j:jsFunction>
    </a4j:form>

    <t:panelGrid id="outPanel" binding="#{myBean.htmlPanelGrid}"/>

    <h:commandButton value="Click me" onclick="setParameterAndRerender('MyValue');return false;"></h:commandButton>

Notice that I set return false in the onclick of the commandButton to avoid it from submitting. I’ll let ajax handle that.

If you create the a4j:support-object progammatically, I’ve experienced that it doesn’t always find the id of the component you have specified to reRender. To solve this, you can use a combination of this one and the javascript function just described:

HtmlAjaxSupport ajaxSupport = new HtmlAjaxSupport();
ajaxSupport.setEvent("onchange");
ajaxSupport.setId("ajaxSupport");
ajaxSupport.setFocus("myForm:theIdOfComponentIWantToFocusOnAfterAjaxSubmit");

//We don't specify reRender id here, but set a javascript function to run when completed
//ajaxSupport.setReRender("myForm:idOFComponentIWantToReRender");
ajaxSupport.setOncomplete("setParameterAndRerender('MyValue');");

myUiComponent.getChildren().add(ajaxSupport);

So, what about the RichFaces library? In all components the ajax capabilities are included, you don’t have to use a4j:support. When using one of the components the submit will always be an ajax submit, so you can just specify which components to reRender. As a short example, instead of using a h:commandButton you can use a4j:commandButton, like this:

    <a4j:commandButton value="Click me" action="#{myBean.action}"  reRender="outPanel"/>
    <t:panelGrid id="outPanel" binding="#{myBean.htmlPanelGrid}"/>

Also, if you have a part of a page that always should be ajaxRendered, and you are tired of of writing Ids to reRender, simply wrap that part of the page inside an a4j:outputPanel and set the ajaxRendered property to true. In my a4j:commandButton, I don’t have to set the reRender property as this panel is now always reRendered by ajax submits:


    <a4j:commandButton value="Click me" action="#{myBean.action}" />

    <a4j:outputPanel ajaxRendered="true">
        <t:panelGrid id="outPanel" binding="#{myBean.htmlPanelGrid}"/>
    </a4j:outputPanel>

I hope this have given you a brief idea of what is possible to do with ajax/richFaces and also how to do it 🙂

I suggest you to check out the livedemo page to see all the different components that RichFaces give you: Live demo

Advertisements

Refresh parent window from child window – conditional reloading with javascript and AJAX

If you work with popups, there will be situations where you need the parent window to update based on some changes/submitted values in the popup window. I will show a solution that is done for myfaces/jsf, and it’s based on the ‘onload’ event of the popup window. I also use ajax (a4j implementation) to update the parent window to avoid a submit and full screen refresh there.

The basic conceptual thoughts about this are quite easy: When you submit a form – or do other actions in your popup that sends data to the server, you need to update the parent window. It could be that you in the popup for example added an item to a table that are displayed in your parent window. So, when you click your button or link in the popup that fires of an action or submit of some sort, you also trigger a javascript on the onclick event that retrieves a hidden button in your parent window and cliks it. This would cause a submit /refresh on you parent window, and the new data that you added from the popup is diplsayed.

Popup.jsp: The popup form with submit button and onclick event:


<h:form id="myPopupForm">
                <t:commandButton id="mySubmit" action="#{myHandler.myAction}" onclick="updateParentWindow();" value="#{messages.myMessage}" >
                </t:commandButton>
</h:form>

Parent.jsp: The parent window hidden button that submits the form or in other ways (onclick event) refreshes that page

<h:form id="updateParentForm" >
        <t:commandButton style="display: none; visibility: hidden;" id="updateParentButton" action="#{myHandler.myAction}"></t:commandButton>
 </h:form>

The script that finds the parent button and clicks it

function updateParentWindow()
{
    var elementToGet = "updateParentForm"+ ":" + "updateParentButton";

    var form = document.forms['updateParentForm'];

    var button = form.elements[elementToGet];

    button.click();
}

But then, if we do it like this – what are the guarantee that the action we fired off in the popup is finished before the parent view is refreshed? None. If we do a submit in the popup, that page will reload. During reloading there is an onload-event that is called, and the popup is not reloaded until the action we fired off has finished. In other words, putting the function inside the onload-event is safe, it will never refresh the parent window before the submit you did is completed. So, let’s move the call of the updateParentWindow()-function from the button to the onload-event of the popup-page:Popup.jsp

<f:verbatim>
    <body onload="updateParentWindow();">
</f:verbatim>

If you now try your application you should se that if you submit the popup, as soon as it has reloaded, your parent window will refresh as well. Nice! This is one big step in the right direction. But there are still some issues to deal with. If I open my popup-window for the first time, I don’t want my parent window to refresh, cause I haven’t done any changes to the data in my popup yet. Having the updateParentWindow() call in the onload event as it is in the example abowe would cause the parent window to be refreshed also the first time the window opens.We want to avoid this, therefore we add some knowledge that the onload event should only trigger the function if the popup page was reloaded by some clicks/submit in the popup-page itself. What we do is to add a boolean value in javascript somewhere inside the body (not the head) of the parent page. It defaults to false, but the links/buttons in the popup will call a small function that set’s this property to true. Then we do a conditional test in the onload event, and only continue if this value is true.The javascript boolean inside the body of the parent page:Parent.jsp

<f:verbatim>
    <script type="text/javascript">
        var fromPopup = false;
    </script>
</f:verbatim>

Our links and buttons in the popup will on the onclick-event set this property to true:Popup.jsp


<h:commandLink onclick="window.opener.fromPopup = true;" action="#{myHandler.myAction}">
        <h:outputText value="myAction"></h:outputText>
</h:commandLink>

And then the conditional reloading would be like this:


<f:verbatim>
    <body onload="if(window.opener.fromPopup)updateParentWindow(); window.opener.fromLink = false;">
</f:verbatim>

It is important to notice that we have to reset the boolean window.opener.fromLink whenever the popup reloads, but we need to do it AFTER the test.

If you are pleased by this solution, no further steps are necessary! But in my application I display a lot of data at the same time, and what I updated in my popup is only a small part of the view in the parent window. Therefore I only wanted to refresh that part of the page, not do a full refresh/reload of my parent window.To do this I use the a4j:commandButton, which has ajax-capabilities and gives me the possibility of rerendering only a part of the page. If you remember we had a hidden button in our parent window that when clicked was responsible for refreshing that page. We modify it a bit, and create an a4j:commandButton instead, and add the reRender property to update the view:Parent.jsp

<a4j:form id="updateParentForm" >
		<a4j:commandButton style="display: none;" id="updateParentButton"  reRender="myComponentOutsideAForm" ></a4j:commandButton>
</a4j:form>

Notice that the area/component I decide to rerender is given by it’s id. Rerendering a component inside a form will fail in Firefox, you will get an error message in the console saying “f has no properties,” and all cliks on links from this point would not work. So either you would have to go for the ordinary submit/refresh, or you can only update areas of the page that doesn’t contain forms. So, applying this code, if you now trigger your submit in the popup page you will se that when it reloads it updates the parent window, but only the part you specified in the ajax-function we created. Avoiding a full refresh gives a better user experience as well as it saves you from retrieving data from the server more than necessary.

Then, what about form validation? Whether you use application validation (business-logic validation in your action methods), or you use the builtin jsf conversion/validation options, or both, it should be possible to handle this as well. If we click a link or button, but the validation fails, we don’t want to update the parent window. This can be done by adding a boolean on the top of our popup.jsp, as well as using this boolean in our updateParentWindow function. Whenever we do an action from the popup, this boolean must be set. If it is business logic validation, it would be easy to set a property if not all requirements are met. If you use the builtin conversion/validation in jsf, you can use the FacesContext.getMessages() to do this. In the popup.jsp, everytime it loads, we get the boolean from our backing bean and pass it on to the javascript. This would avoid the parentWindow to be updated if validation fails.

First, modify the script we use to update parent to respect a boolean parameter:

function updateParentWindow(validationFailed)
{
    if(validationFailed)
	return;
    else
   {
    var elementToGet = "updateParentForm"+ ":" + "updateParentButton";

    var form = document.forms['updateParentForm'];

    var button = form.elements[elementToGet];

    button.click();
   }
}

In the handler we need a boolean property that we can set depending on whether the validation failed or not. We create a private method that will help us to set this boolean, the important thing is that we call it from all our action methods. So the handler might look something like this:

public class MyHandler
{
    private boolean validationFailed = false;

    //Action
    public void doSomething()
    {
        ...
        Some code/business logic
        ...

        If some business logic/validation is not correct, pass this on to the validation method
            setValidation(true);
        If business logic/validation is correct
            setValidation(false);

    }

    private void setValidation(boolean applicationValidationFailed)
    {
        FacesContext context = FacesContext.getCurrentInstance();
        Iterator<FacesMessage> messages = context.getMessages();
        if(messages.hasNext() || applicationValidationFailed)
            setValidationFailed(true);
        else
            setValidationFailed(false);
    }
}

Then on top of our popup jsp inside <% %> tags we retrieve the handler, and we store the boolean property inside a local variable:

<%

MyHandler myHandler = (MyHandler)FacesContext.getCurrentInstance().getApplication ().
getVariableResolver().resolveVariable(FacesContext.getCurrentInstance(),"myHandler");
boolean validationFailed = myHandler.isValidationFailed();
%>

And then we also modify the onload of this page to pass the boolean to the javascript:


<f:verbatim>
    <body onload="if(window.opener.fromPopup)updateParentWindow(<%= validationFailed %>); window.opener.fromLink = false;">
</f:verbatim>

Done! Your popup-page should also respect the validation now, and not update the parent if it fails.

I hope that this example will be helpful, and if not completely adaptable to your requirements it might lead you into the right path. I end this post by showing the popup.jsp and the parent.jsp in whole, to make it easier for you to see what I’ve tried to explain:Parent.jsp

<f:view  >
    <t:document>
    <t:documentHead>
    ...
    </t:documentHead>

    <f:verbatim>
    <body>
    </f:verbatim>

  <f:verbatim>
    <script type="text/javascript">
    //Used in popup
    var fromLink = false;
    </script>
    </f:verbatim>            

    Some content
    ...

    ...

    <h:panelGrid id="myComponentOutsideAForm">
        THIS AREA/CONTENT WILL BE REFRESHED
    </h:panelGrid>

    <a4j:form id="updateParentForm" >
        <a4j:commandButton style="display: none;" id="updateParentButton"  reRender="myComponentOutsideAForm" ></a4j:commandButton>
   </a4j:form>  

<f:verbatim>
    </body>
</f:verbatim>

</t:document>

</f:view>

Popup.jsp

<f:view  >
    <t:document>
    <t:documentHead>
    ...
    </t:documentHead>
<%

MyHandler myHandler = (MyHandler)FacesContext.getCurrentInstance().getApplication ().
getVariableResolver().resolveVariable(FacesContext.getCurrentInstance(),"myHandler");
boolean validationFailed = myHandler.isValidationFailed();
%>
<f:verbatim>
<body onload="if(window.opener.fromPopup)updateParentWindow(<%= validationFailed %>); window.opener.fromLink = false;">

</f:verbatim>

    Some content
    ....

    ....

   <h:commandLink onclick="window.opener.fromPopup = true;" action="#{myHandler.myAction}">
    <h:outputText value="myAction"></h:outputText>
   </h:commandLink>  

<f:verbatim>
</body>
</f:verbatim>

</t:document>
</f:view>