显示时modalPanel延迟渲染

时间:2010-07-07 10:35:20

标签: jsf richfaces

动机:我想在访问时减小页面的大小,所以我认为modalPanels上的延迟渲染会有所帮助。想法是在用户单击显示它的链接时呈现modalPanel。

我想在点击显示它的链接时在rich:modalPanel上进行延迟渲染。为实现这一目标,我找到了一种方法:

modalPanel的代码,包含在a4j:outputPanel

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

支持bean的代码(会话范围):

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

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

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

调用它的页面代码:

<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>

问题:

  • modalPanel需要包含在a4j:outputPanel内,因为直接重新调整modalPanel不起作用(我从不理解为什么)。

  • 渲染后,需要额外的请求将渲染值设置为false(bean是会话范围的)。否则,如果我们重新加载页面,则不会有任何延迟渲染,因为该值设置为true

  • 支持bean必须处理一个属性以保持每个modalPanel的状态,尽管每当单击链接时此属性设置为true,并且当请求为false时完了。我试图将rendered状态保留为JS变量,但它似乎不起作用(只有在页面加载后才会读取它们,而不会再次读取。)

更优雅的方式吗?

3 个答案:

答案 0 :(得分:7)

关于你的问题有一个很好的解决方案。所有需要的是一种检测回发和几个xhtmls的方法。

首先,我们需要一个有助于指示回发的bean

public class HelperBean {

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

}

empty.xhtml - 表示空白内容

<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">

</ui:composition>

modal.xhtml - 用于包装模态定义

<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">

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

lazyModal.xhtml - 用于处理包含上述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">

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

最后使用它

   <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>

现在加载页面时,将包含empty.xhtml,直到btnSubmit被点击。


关于你提到的问题(1):

使用渲染属性重新渲染组件有点吸引人。当渲染表达式计算为false时,不会将标记发送回客户端。因此,将无渲染组件的id提供给reRender属性将永远不会起作用,因为客户端(DOM)上没有此类ID。

答案 1 :(得分:1)

我认为你应该制作模态面板的单独xhtml(facelet)并使用ui:include而不是链接点击链接,不需要布尔属性。

enter code here : <ui:include src="modalPanel path">, <a4j:commandLink id="abclink" oncomplete="#{rich:component('yourPanelname')}.show()" reRender="yourPanelForm"/>

答案 2 :(得分:1)

另一个解决方案是在JSF组件树中以编程方式设置modalpanel的render属性。因此,您不需要额外的支持bean,它必须处理一个属性以保持每个modalPanel的状态:

Managed Bean:

public void togglePanel(ActionEvent event) {
    UIComponent component = event.getComponent();
    String forId = (String) component.getAttributes().get("for");

    FacesContext currentInstance = FacesContext.getCurrentInstance();
    UIComponent findComponent = ComponentFinder.findComponent(currentInstance.getViewRoot(), forId);
    findComponent.setRendered(!findComponent.isRendered());
}

查看:

打开面板:

<a4j:commandLink actionListener="#{myBean.togglePanel}" value="Open">
<f:attribute name="for" value="targetPanelId" />

关闭Panel:

<a4j:commandLink id="closePanel" actionListener="#{myBean.togglePanel}" value="someLabel">
<f:attribute name="for" value="targetPanelId" />

模态面板:

<a4j:outputPanel ajaxRendered="true">
        <rich:modalPanel id="targetPanelId" width="800" height="500" rendered="false" showWhenRendered="true">