modalPanel ленивый рендеринг при отображении

Мотивация: я хочу уменьшить размер страницы при доступе, поэтому я подумал, что ленивый рендеринг на modalPanels поможет. Идея состоит в том, чтобы отображать modalPanel, когда пользователь щелкает ссылку, которая отображает его.

Я хочу лениво отображать rich:modalPanel при нажатии ссылки для ее отображения. Для этого я нашел способ:

Код modalPanel, заключенный в a4j:outputPanel

 <a4j:outputPanel id="a4jPanel">
  <rich:modalPanel id="panel" rendered="#{bean.renderPanel}">
         <!-- here modalPanel things -->
  </rich:modalPanel>
 </a4j:outputPanel>

Код вспомогательного компонента (область сеанса):

   public boolean isRenderPanel() {
   return renderPanel;   //default value is false;
   }

    public void setRenderPanel(boolean value){
           this.renderPanel=value;
    }

    public setRenderFalse(){
           this.setRenderPanel(false);
    }

Код страницы, на которой он вызывается:

<a4j:form>
<a4j:jsFunction name="setRenderFalse" action="#{user.setRenderFalse}"/>
<a4j:commandLink value="render and show"  oncomplete="Richfaces.showModalPanel('panel');setRenderFalse();" reRender="a4jPanel">
<f:setPropertyActionListener target="#{user.renderPanel}" value="true" />
</a4j:commandLink>
</a4j:form>

Проблемы:

  • modalPanel должен быть обернут внутри a4j:outputPanel, потому что reRendering непосредственно modalPanel не работает (я никогда не понимал, почему).

  • После его рендеринга необходим дополнительный запрос, чтобы установить значение рендеринга в false (бин находится в пределах сеанса). В противном случае, если мы перезагрузим страницу, не будет никакого ленивого рендеринга, потому что значение было установлено на true.

  • Компонент поддержки должен обрабатывать одно свойство, чтобы сохранить состояние для каждой modalPanel, хотя это свойство устанавливается в true всякий раз, когда нажимается ссылка, и устанавливается в false по завершении запроса. Я пытался сохранить состояние rendered с переменными JS, но, похоже, это не работает (они просто считываются после загрузки страницы и никогда больше).

Есть ли более элегантный способ сделать это?


person pakore    schedule 07.07.2010    source источник


Ответы (3)


Есть хорошее решение по вашему вопросу. Все, что нужно, это способ обнаружения обратной передачи и пара xhtml.

В первую очередь нам нужен бин, который поможет с индикацией постбэка

public class HelperBean {

    public boolean isPostback() {
        FacesContext context = FacesContext.getCurrentInstance();
        return context.getRenderKit().getResponseStateManager().isPostback(context);
    }

}

empty.xhtml - для пустого контента

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:c="http://java.sun.com/jstl/core"
    xmlns:a4j="http://richfaces.org/a4j"
    xmlns:rich="http://richfaces.org/rich">

</ui:composition>

modal.xhtml — для упаковки модального определения

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:c="http://java.sun.com/jstl/core"
    xmlns:a4j="http://richfaces.org/a4j"
    xmlns:rich="http://richfaces.org/rich">

    <rich:modalPanel id="myLazyModal">
        <h:outputText value="Modal Content"/>
    </rich:modalPanel>
</ui:composition>

lazyModal.xhtml — для обработки включения вышеуказанных xhtml

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:c="http://java.sun.com/jstl/core"
    xmlns:a4j="http://richfaces.org/a4j"
    xmlns:rich="http://richfaces.org/rich">

    <a4j:include id="lazyModal" layout="block"
        viewId="#{helperBean.postback ? 'modal.xhtml' : 'empty.xhtml'}"/>
</ui:composition>

наконец использовать его

   <h:form id="frmTest">
        <a4j:include id="lazyModalContainer" layout="block" viewId="lazyModal.xhtml"/>
        <a4j:commandButton id="btnSubmit" value="Submit" reRender="lazyModalContainer"
            oncomplete="Richfaces.showModalPanel('myLazyModal');"/>
   </h:form>

Теперь, когда страница загружается, пустой.xhtml будет включен до тех пор, пока не будет нажата btnSubmit.


Что касается проблем, которые вы упомянули (1):

Повторный рендеринг компонентов с атрибутом rendered немного цепляет. Когда отображаемое выражение оценивается как false, никакая разметка не отправляется обратно клиенту. Таким образом, предоставление идентификатора компонента без рендеринга в атрибут reRender никогда не будет работать, потому что такого идентификатора нет на стороне клиента (DOM).

person Maxim Manco    schedule 08.08.2010
comment
Похоже на чистое решение. Я собираюсь попробовать это. Если это сработает, награда ваша :) - person pakore; 09.08.2010
comment
Только один вопрос: но как это возможно, что когда вы нажимаете на a4j: commandButotn, он показывает modalPanel, поскольку modalPanel не отображается и нет компонента с идентификатором «myLazyModal»? Проблема в том, что я использую новый синтаксис #{rich:component('myLazyModal')}.show(), который, я думаю, оценивается как null - person Luca Molteni; 17.12.2010
comment
вы по-прежнему можете использовать #{rich:component('myLazyModal')}.show(). Обратите внимание, что в этом случае вы должны использовать его, когда запускается oncomplete. - person Maxim Manco; 26.12.2010

я думаю, вам следует сделать отдельный xhtml (facelet) модальной панели и использовать ui:include, а затем по ссылке щелкнуть ссылку, не требующую логического свойства, чем.

enter code here : <ui:include src="modalPanel path">, <a4j:commandLink id="abclink" oncomplete="#{rich:component('yourPanelname')}.show()" reRender="yourPanelForm"/>
person Community    schedule 14.07.2010
comment
modalPanel уже представляет собой отдельный xhtml, вставленный с помощью ui:include. Когда вы включаете файл, jsf вставляет код внутрь контейнера, поэтому он предназначен для рендеринга, он рендерится. - person pakore; 14.07.2010
comment
Да, ты прав, но это единственный способ ui:include. Ленивый рендеринг может быть невозможен. Я проверю, есть ли какое-то решение..... Добрый день - person TaherT; 15.07.2010

Другим решением является программная установка атрибута рендеринга вашей модальной панели в дереве компонентов JSF. Таким образом, вам не понадобится дополнительный компонент поддержки, который должен обрабатывать одно свойство, чтобы сохранить состояние для каждой modalPanel:

Управляемый компонент:

public void togglePanel(ActionEvent event) {
    UIComponent component = event.getComponent();
    String forId = (String) component.getAttributes().get("for");

    FacesContext currentInstance = FacesContext.getCurrentInstance();
    UIComponent findComponent = ComponentFinder.findComponent(currentInstance.getViewRoot(), forId);
    findComponent.setRendered(!findComponent.isRendered());
}

Вид:

Откройте панель:

<a4j:commandLink actionListener="#{myBean.togglePanel}" value="Open">
<f:attribute name="for" value="targetPanelId" />

Close the Panel:

<a4j:commandLink id="closePanel" actionListener="#{myBean.togglePanel}" value="someLabel">
<f:attribute name="for" value="targetPanelId" />

The modalpanel:

<a4j:outputPanel ajaxRendered="true">
        <rich:modalPanel id="targetPanelId" width="800" height="500" rendered="false" showWhenRendered="true">
person Born78    schedule 07.05.2013