JSF ленивое значение загрузки компонента

Рассмотрим простой компонент h:outputText:

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

Как я могу лениво загрузить это значение после рендеринга страницы и отображать собственный значок "ajax loading" вместо значения, пока это делается?

Я использую PrimeFaces 3.5 в своем проекте, поэтому приветствуется любая специфичная для PF реализация.

3 ответа

Решение

Предлагаю сделать это по телефону remoteCommand после загрузки страницы (это делается путем настройки autoRun атрибут true) и обновите свой 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 первое добавление boolean свойство в вашем бэк-бине, и установите для этого свойства значение true в конце initMyValue метод:

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

Вот как я это реализовал:

<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. Мне нужно реализовать отдельный метод на моем компоненте поддержки (getUserLoginLocation), чтобы получить значение и явно сохранить его в другом свойстве (lastLoginLocation). Было бы намного чище просто иметь один геттер, который называется ленивым после рендеринга страницы в браузере
  3. Нелегко повторно использовать - зависит от флага загруженного бина поддержки (в данном случае # {empty myBean.lastLoginLocation}) и требует, чтобы слушатель действия фактически установил значение. Любой составной компонент, основанный на этом подходе, также будет зависеть от конкретного кода в компоненте поддержки.

Любые рекомендации по улучшению этого кода приветствуются!:)

Вы можете использовать BlockUI для условной блокировки компонента во время его загрузки.

  1. Определить preRenderComponent событие на <h:outputText/>

       <h:outputText id="myText">
          <f:event name="preRenderComponent" id="started"/>
       </h:outputText>
    
  2. Определить <p:blockUI/> с идентификатором события в качестве триггера

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

Вы можете настроить blockui для отображения изображения или чего-либо еще.

Предостережение: я полагаю, что вам нужно это, потому что вы выполняете тяжелую работу по получению этого компонента. Знайте, что геттер будет вызываться несколько раз в течение жизненного цикла этой страницы. Таким образом, сокрытие факта, что операция занимает много времени, не изменит факт. Лучшим вариантом было бы предварительно загрузить и кэшировать значение для этого компонента в долговременной области, а не в виде "загружаемого" пульсатора.

Другие вопросы по тегам