简体   繁体   English

JSF延迟加载组件值

[英]JSF lazy loading component value

Consider a simple h:outputText component: 考虑一个简单的h:outputText组件:

<h:outputText value="#{myBean.myValue}"/>

How can I lazy load that value after the page has been rendered, and display custom 'ajax loading' icon instead of the value while this is being done? 如何在页面渲染后延迟加载该值,并在完成此操作时显示自定义'ajax loading'图标而不是值?

I am using PrimeFaces 3.5 in my project so any PF-specific implementation will be welcome. 我在我的项目中使用PrimeFaces 3.5,因此欢迎任何特定于PF的实现。

A suggest to do this by calling remoteCommand after on page load (it is done by setting autoRun attribute to true) and update your outputText . 建议通过在页面加载后调用remoteCommand来完成此操作(通过将autoRun属性设置为true来完成)并更新outputText

private String myValue;

// getter and setter

public void initMyValue() {
  // init myValue
}

On page you should have ajaxStatus component for viewing loading image, and your outputText . 在页面上,您应该有ajaxStatus用于查看加载图像的ajaxStatus组件和outputText Also there should be p:remoteCommand component: 还应该有p:remoteCommand组件:

<p:ajaxStatus style="width:16px;height:16px;" id="ajaxStatusPanel">  
  <f:facet name="start">  
    <h:graphicImage value="ajaxloading.gif" />  
  </f:facet>
  <f:facet name="complete">  
    <h:outputText value="" />
  </f:facet>  
</p:ajaxStatus>

<h:outputText id="myText" value="#{myBean.myValue}"/>

<p:remoteCommand autoRun="true" actionListener="#{myBean.initMyValue}" update="myText"/>

EDIT: I supposed that you want to lazy load value of outputText because it contains some long running calculations, but if you want to completely deffer rendering of outputText first add boolean property in your backing bean, and set this property to true at the end of initMyValue method: 编辑:我认为你想延迟加载outputText值,因为它包含一些长时间运行的计算,但如果你想完全deffer的outputText渲染首先在你的支持bean中添加boolean属性,并在结束时将此属性设置为true initMyValue方法:

private boolean loaded;

// getter and setter

public void initMyValue() {
  // init myValue
  loaded = true;
}

on the page reorganize it as follows: 在页面上重新组织如下:

<h:panelGroup id="myPanel" layout="block">
  <h:graphicImage value="ajaxloading.gif" rendered="#{!myBean.loaded}"/>
  <h:outputText value="#{myBean.myValue}" rendered="#{myBean.loaded}"/>
</h:panelGroup>

<p:remoteCommand autoRun="true" actionListener="#{myBean.initMyValue}" update="myPanel"/>

You can use a BlockUI to conditionally block the component while it loads. 您可以使用BlockUI在加载时有条件地阻止组件。

  1. Define a preRenderComponent event on the <h:outputText/> <h:outputText/>上定义preRenderComponent事件

      <h:outputText id="myText"> <f:event name="preRenderComponent" id="started"/> </h:outputText> 
  2. Define a <p:blockUI/> with the id of the event as the trigger 使用事件的id作为触发器定义<p:blockUI/>

      <p:blockUI block="myText" trigger="started" /> 

You can customize the blockui to display an image or whatever. 您可以自定义blockui以显示图像或其他任何内容。

A word of caution: I presume you require this because you're doing some heavy lifting in the getter of that component. 需要注意的是:我认为你需要这个,因为你在那个组件的吸气器中做了一些繁重的工作。 Know that the getter will be called several times in the lifecycle of that page. 知道在该页面的生命周期中将多次调用getter。 So hiding the fact that the operation is taking a long time will not change the fact. 因此,隐藏操作需要很长时间的事实不会改变这一事实。 A better design would be to preload and cache the value for that component in a durable scope, rather than the theatrics of a "loading" throbber. 更好的设计是在持久范围内预加载和缓存该组件的值,而不是“加载”悸动者的方案。

This is how I ended up implementing it: 这就是我最终实现它的方式:

<h:panelGroup id="loginLocation">
<p:graphicImage library="assets" name="small-kit-loader.gif" width="16" height="16" rendered="#{empty mybean.lastLoginLocation}"></p:graphicImage> 
<h:outputText value="#{myBean.lastLoginLocation}" rendered="#{!empty myBean.lastLoginLocation}"/>
</h:panelGroup>
<p:remoteCommand global="false" actionListener="#{actionBean.getUserLoginLocation(myBean.selectedUser)}" name="refreshLoginLocation" id="rc1" autoRun="true" update="loginLocation" process="@this"></p:remoteCommand>

Personally I am not entirely happy with this implementation: 我个人对这个实现并不完全满意:

  1. lazy loading state is stored server-side, not client-side where it should be 延迟加载状态存储在服务器端,而不是客户端应该存在的位置
  2. I have to implement separate method on my backing bean (getUserLoginLocation) to retrieve the value, and explicitly store it in another property (lastLoginLocation). 我必须在我的支持bean(getUserLoginLocation)上实现单独的方法来检索值,并将其显式存储在另一个属性(lastLoginLocation)中。 It would have been much cleaner just to have a single getter that is lazy-called after rendering the page in browser 在浏览器中渲染页面后,只需要一个懒惰的单个getter就可以了
  3. Not easily reusable - depends on backing bean 'loaded' flag (#{empty myBean.lastLoginLocation} in this case), and requires action listener to actually set the value. 不容易重用 - 取决于支持bean'loaded'标志(在这种情况下为#{empty myBean.lastLoginLocation}),并且需要动作侦听器来实际设置值。 Any composite component based on this approach would also depend on specific code in backing bean. 基于此方法的任何复合组件也将依赖于辅助bean中的特定代码。

Any recommendations on how to improve this code are welcome! 欢迎任何有关如何改进此代码的建议! :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM