2013-03-13 37 views
4

考慮一個簡單的H:outputText組件:JSF懶加載組件值

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

我怎麼能延遲加載該頁面後,價值已經呈現,並且代替值,同時顯示自定義「AJAX加載」圖標這是正在完成?

我在我的項目中使用PrimeFaces 3.5,所以任何PF特定的實現將受到歡迎。

回答

6

建議在頁面加載後(通過將autoRun屬性設置爲true)調用remoteCommand並更新outputText來完成此操作。

private String myValue; 

// getter and setter 

public void initMyValue() { 
    // init myValue 
} 

在頁面上,你應該有ajaxStatus組件用於查看加載圖像,和你的outputText。還應該有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"/> 

編輯:我應該要的outputText延遲加載的價值,因爲它包含了一些長時間運行的計算,但如果你想的outputText完全deffer呈現先加boolean在你的後臺bean的屬性,將此屬性設置爲trueinitMyValue方法的末尾:

private boolean loaded; 

// getter and setter 

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

在頁面上重新組織如下:

<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"/> 
+0

看起來像它會工作,但也意味着myText將在頁面呈現期間急切加載。我怎樣才能避免這種情況?我意識到我可以在後臺bean中做到這一點,但只要延遲加載就好了。此外,在這種情況下,ajaxStatus將是全局的 - 我只想顯示一個加載狀態來代替專門爲此組件設置的值。謝謝! – rootkit 2013-03-13 16:28:05

+0

我編輯了一個答案。我添加了可能更適合您需求的部分。 – partlov 2013-03-14 07:48:24

+0

是的,這經過一些調整後才起作用。儘管如此,對於這樣一個簡單的任務來說,上述所有方面都是太麻煩了。沒有更優雅的解決方案嗎?我會寫一個組件來做懶惰的渲染...... – rootkit 2013-03-14 16:27:14

1

您可以使用BlockUI在加載組件時有條件地阻止該組件。

  1. 定義在<h:outputText/>

    <h:outputText id="myText"> 
         <f:event name="preRenderComponent" id="started"/> 
        </h:outputText> 
    
  2. 一個preRenderComponent事件定義<p:blockUI/>與事件的ID作爲觸發

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

您可以自定義blockui到顯示圖像或其他。

謹慎的一句話:我認爲你需要這個,因爲你在這個組件的getter中做了一些繁重的工作。知道getter將在該頁面的生命週期中多次調用。因此隱瞞手術花費很長時間的事實不會改變事實。一個更好的設計將是在一個持久的範圍內預加載和緩存該組件的值,而不是「加載」跳動者的表演。

+0

嘗試過,但在我的頁面顯示給用戶之前調用preRenderComponent事件偵聽器。這是一個模態動態的PF對話框 - 想知道這與它有什麼關係?此外,我完全理解你在緩存持久範圍中的值時所說的話 - 在這種情況下,我有API調用來將IP地址解析爲位置,並且由於API調用的數量有限,我寧願不這樣做,除非用戶真正查看數據。 – rootkit 2013-03-14 14:52:18

+0

@rootkit,現在有更好的上下文,我可以建議一個更合適的解決方案。在對話框中設置'dynamic =「true」'來阻止加載頁面時加載對話框的內容。此外,可以使outputText的'rendered'屬性有條件,以確保該元素僅在需要時才放入DOM中 – kolossus 2013-03-14 15:11:57

+0

該對話框已經是動態的,但我多次顯示它。我只想在用戶打開對話框時查找位置,並且由於查找需要好幾秒鐘,我不想延遲打開對話框...... – rootkit 2013-03-14 16:14:22

1

這是我怎麼會實現它:

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

個人我不是這個實現完全滿意:

  1. 延遲加載狀態被存儲在服務器端,而不是客戶端,其中它應該是
  2. 我必須在我的支持bean(getUserLoginLocation)上實現單獨的方法來檢索值,並將其顯式存儲在另一個屬性(lastLoginLocation)中。如果在瀏覽器中渲染頁面之後調用一個單獨的getter將會更簡潔
  3. 不容易重用 - 取決於backing bean的'loaded'標誌(在這種情況下,#{empty myBean.lastLoginLocation}) ,並要求動作偵聽器實際設置該值。基於這種方法的任何複合組件都將依賴於backing bean中的特定代碼。

歡迎任何有關如何改進此代碼的建議! :)