tags:

views:

98

answers:

2

Motivation: I want to reduce the size of the page when is accessed, so I thought that lazy rendering on modalPanels would help. The idea is to render the modalPanel when the user clicks the link that displays it.

I want to lazy render on rich:modalPanel when the link to display it is clicked. To achieve this I've found a way:

Code of the modalPanel, wrapped inside a a4j:outputPanel

 <a4j:outputPanel id="a4jPanel">
  <rich:modalPanel id="panel" rendered="#{bean.renderPanel}">
         <!-- here modalPanel things -->
  </rich:modalPanel>
 </a4j:outputPanel>

Code of the backing bean (session scope):

   public boolean isRenderPanel() {
   return renderPanel;   //default value is false;
   }

    public void setRenderPanel(boolean value){
           this.renderPanel=value;
    }

    public setRenderFalse(){
           this.setRenderPanel(false);
    }

Code of the page where it is invoked:

<a4j:form>
<a4j:jsFunction name="setRenderFalse" action="#{user.setRenderFalse}"/>
<a4j:commandLink value="render and show"  oncomplete="Richfaces.showModalPanel('panel');setRenderFalse();" reRender="a4jPanel">
<f:setPropertyActionListener target="#{user.renderPanel}" value="true" />
</a4j:commandLink>
</a4j:form>

Problems:

  • The modalPanel needs to be wrapped inside an a4j:outputPanel because reRendering directly the modalPanel does not work (I never understood why).

  • After rendering it, an extra request is needed to set the render value to false (the bean is session scoped). Otherwise if we reload the page there would not be any lazy rendering because the value was set to true.

  • The backing bean has to handle one property to keep the state for each modalPanel, although this property is set to true whenever the link is clicked and set to false when the request is finished. I've tried to keep the rendered state with JS variables but it does not seem to work (they are just read once the page is loaded and never again).

Any more elegant way to do this?

A: 

i think you should make separate xhtml(facelet) of modal panel and use ui:include and than on link click the link no need of boolean property than.

enter code here : <ui:include src="modalPanel path">, <a4j:commandLink id="abclink" oncomplete="#{rich:component('yourPanelname')}.show()" reRender="yourPanelForm"/>
taher
The modalPanel is already a separate xhtml inserted with `ui:include`. When you include a file, jsf pastes the code inside the container, so it is meant to be rendered, it is rendered.
pakore
ya you are right but that is the only way ui:include. Lazy render is might not possible. I'll check if there some solution..... Good Day
taher
+3  A: 

There is a nice solution regarding your question. All is needed is a way to detect postback and couple of xhtmls.

First of all we need a bean that will help with indication of postback

public class HelperBean {

    public boolean isPostback() {
        FacesContext context = FacesContext.getCurrentInstance();
        return context.getRenderKit().getResponseStateManager().isPostback(context);
    }

}

empty.xhtml - for a blank content

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:c="http://java.sun.com/jstl/core"
    xmlns:a4j="http://richfaces.org/a4j"
    xmlns:rich="http://richfaces.org/rich"&gt;

</ui:composition>

modal.xhtml - for wrapping the modal definition

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:c="http://java.sun.com/jstl/core"
    xmlns:a4j="http://richfaces.org/a4j"
    xmlns:rich="http://richfaces.org/rich"&gt;

    <rich:modalPanel id="myLazyModal">
        <h:outputText value="Modal Content"/>
    </rich:modalPanel>
</ui:composition>

lazyModal.xhtml - for handling inclusion of the above xhtmls

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:c="http://java.sun.com/jstl/core"
    xmlns:a4j="http://richfaces.org/a4j"
    xmlns:rich="http://richfaces.org/rich"&gt;

    <a4j:include id="lazyModal" layout="block"
        viewId="#{helperBean.postback ? 'modal.xhtml' : 'empty.xhtml'}"/>
</ui:composition>

finally use it

   <h:form id="frmTest">
        <a4j:include id="lazyModalContainer" layout="block" viewId="lazyModal.xhtml"/>
        <a4j:commandButton id="btnSubmit" value="Submit" reRender="lazyModalContainer"
            oncomplete="Richfaces.showModalPanel('myLazyModal');"/>
   </h:form>

Now when the page is loaded empty.xhtml will be included till btnSubmit is clicked.


Regarding to the problems you mentioned (1):

Re-rendering components with the rendered attribute is a bit catchy. When the rendered expression is evaluated to false no markup is sent back to the client. Therefore, supplying the id of the none rendered component to the reRender attribute will never work cause there is no such id on the client side (DOM).

mmanco
Seems like a clean solution. I'm gonna try it out. If it works, the bounty is yours :)
pakore
It worked just fine! Thanks.
pakore
Great, glad it helped.
mmanco