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>
Лично я не совсем доволен этой реализацией:
- Ленивое состояние загрузки сохраняется на стороне сервера, а не на стороне клиента, где это должно быть
- Мне нужно реализовать отдельный метод на моем компоненте поддержки (getUserLoginLocation), чтобы получить значение и явно сохранить его в другом свойстве (lastLoginLocation). Было бы намного чище просто иметь один геттер, который называется ленивым после рендеринга страницы в браузере
- Нелегко повторно использовать - зависит от флага загруженного бина поддержки (в данном случае # {empty myBean.lastLoginLocation}) и требует, чтобы слушатель действия фактически установил значение. Любой составной компонент, основанный на этом подходе, также будет зависеть от конкретного кода в компоненте поддержки.
Любые рекомендации по улучшению этого кода приветствуются!:)
Вы можете использовать BlockUI для условной блокировки компонента во время его загрузки.
Определить
preRenderComponent
событие на<h:outputText/>
<h:outputText id="myText"> <f:event name="preRenderComponent" id="started"/> </h:outputText>
Определить
<p:blockUI/>
с идентификатором события в качестве триггера<p:blockUI block="myText" trigger="started" />
Вы можете настроить blockui для отображения изображения или чего-либо еще.
Предостережение: я полагаю, что вам нужно это, потому что вы выполняете тяжелую работу по получению этого компонента. Знайте, что геттер будет вызываться несколько раз в течение жизненного цикла этой страницы. Таким образом, сокрытие факта, что операция занимает много времени, не изменит факт. Лучшим вариантом было бы предварительно загрузить и кэшировать значение для этого компонента в долговременной области, а не в виде "загружаемого" пульсатора.