JSF 2.0:延迟渲染(复合)组件的内容,直到AJAX调用重新渲染它

问题描述:

我的目标是动态加载JSF 2.0中组件的内容。用例是这样的:用户点击一些按钮,通过AJAX打开一些带有大量内容的模式面板。由于它的沉重感,我想延迟加载直到/如果用户实际需要它。如果用户关闭此面板,它实际上并未从DOM中删除,只是淡出。如果用户再次点击初始化按钮,则显示先前加载的面板。JSF 2.0:延迟渲染(复合)组件的内容,直到AJAX调用重新渲染它

我知道我可以防止使用rendered="#{cc.attrs.visibilityState == 'hidden'}"呈现内容,并且我可以通过JSF AJAX调用重新呈现组件。但是,如何即时调整复合组件的属性,以便围绕组件第二次实际渲染?

1)我知道我可以这样做:

<h:outputLink>Foo 
    <f:ajax event="click" render="theComponentIWantToUpdate" listener="#{someBean.someMethod()}" /> 
</h:outputLink> 

,然后以编程调整theComponentIWantToUpdate属性(改变#{cc.attrs.visibilityState}值),因此它实际上与完整内容呈现。但如何真正做到这一点?

2)另外,问题是我不想每次按下按钮时更新(重新呈现)theComponentIWantToUpdate,只是第一次(请参阅业务案例)。如何为此设置<f:ajax />电话评估?它具有disabled属性,但它仅命令是否实际呈现AJAX处理程序(每次链接被按下时都未评估)。 3)此外,我可能想首先做一些自定义JavaScript,当链接被点击时,只使用jsf.ajax.request()通过javascript执行AJAX请求。但是,该函数不支持提供listener属性,所以我不怎么执行原始javascript jsf.ajax.request()调用的支持bean方法?实际上有一个类似的问题没有合适的答案(见JSF 2.0 AJAX: jsf.ajax.request to call method not only rerender an area of page)。

+0

好吧我挖自己的部分解决方案作为一个接受的时间之中。如果有人有更好的建议,我会很乐意改变选择:) – 2010-09-28 12:41:14

的部分解决方案:

这是我的链路发送一个AJAX请求(复合部件的内部):

<h:form> 
    <h:outputLink styleClass="modlet-icon"> 
     <f:ajax event="click" render=":#{cc.clientId}:modalWindow:root" listener="#{modalWindowBean.enableContentRendering(cc.clientId, 'modalWindow')}" /> 
    </h:outputLink> 
</h:form> 

侦听器调用此方法:

public class ModalWindowBean { 
    ... 

    public void enableContentRendering(String clientId, String windowId) { 
     UIComponent component = FacesContext.getCurrentInstance().getViewRoot().findComponent(clientId + ":" + windowId); 
     component.getAttributes().put("contentRenderingEnabled", true); 
    } 
} 

这里是我的目标:

<modalWindow:modalWindow id="modalWindow"> 
    <quickMenu:quickMenuOverlay id="quickMenuOverlay" /> 
</modalWindow:modalWindow> 

ModalWindow只是将目标包装成一个漂亮的窗口面板。在ModalWindow中:

<composite:implementation> 
    <h:outputScript library="component/modalWindow" name="modalWindow.js" target="head" /> 
    <h:outputStylesheet library="component/modalWindow" name="ModalWindow.css" /> 

    <h:panelGroup id="root" layout="block" styleClass="modalWindow hide"> 
     <ui:fragment rendered="#{cc.attrs.contentRenderingEnabled}"> 
      ...all the wrapping elements with <composite:insertChildren /> within it 
      <script type="text/javascript"> 
       // Fade it in 
       var win = ModalWindow.getInstance('#{cc.clientId}'); // this gets the instance, available everywhere 
       win.position(#{cc.attrs.left}, #{cc.attrs.top}); 
       win.resize(#{cc.attrs.width}, #{cc.attrs.height}); 
       win.fadeIn(); 
      </script> 
     </ui:fragment> 
    </h:panelGroup> 

    <ui:fragment rendered="#{!cc.attrs.contentRenderingEnabled}"> 
     <script type="text/javascript"> 
      // Initialize modalWindow when it is rendered for the first time 
      var win = new ModalWindow('#{cc.clientId}'); // will be publicly available through ModalWindow static methods 
     </script> 
    </ui:fragment> 

</composite:implementation> 

问题?每次用户单击按钮时都会发送AJAX请求(所以每次都重新加载和淡出窗口)。我需要能够控制何时/如果AJAX请求实际发送。

所有这些东西让我怀念的Apache Wicket的,虽然我不知道我会怎么做反正这与它:)