Условное отображение подклассов в интерфейсе JSF: тег повтора - PullRequest
2 голосов
/ 10 марта 2011

аналогично здесь Я использую абстрактный класс для ввода списка наборов элементов UI: повторить . Конкретные подклассы переопределяют метод getType (), который используется для условно отрендерить соответствующий подтип с его конкретными свойствами:

<!-- AbstractAction Rule#getActions() -->
<ui:repeat value="#{rule.actions}" var="action">
  <!-- render when "action" instance of NotificationAction -->
  <h:panelGroup rendered="#{action.type == 'notification'}"> 
    ... UI for NotificationAction properties 
  <h:panelGroup rendered="#{action.type == 'callback'}"> 
    ...

При запуске на Glassfish 3 возникает ошибка из-за того, что свойства не определены в списке члены других подклассов (PropertyNotFoundException), который происходит в ветви, которая фактически отключается рендерингом . c: forEach / c: выбрать не похоже подходящее. Любые идеи, как сделать рендеринг действительно условным и обойти проверка недвижимости высоко ценится!

Спасибо. Яро

1 Ответ

1 голос
/ 11 марта 2011

после некоторого тестирования выяснилось, что сам компонент ui: repeat вызвал ошибку. Несмотря на то, что он находится в финальной фазе RenderResponse , он пытается сохранить состояние своих дочерних компонентов ввода. Вот сокращенный дамп исключения:

Caused by: javax.el.PropertyNotFoundException: ... The class FOO does not have a readable property 'BAR'.
        at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:104)        
        at com.sun.faces.facelets.component.UIRepeat.saveChildState(UIRepeat.java:343)
        at com.sun.faces.facelets.component.UIRepeat.setIndex(UIRepeat.java:428)
        at com.sun.faces.facelets.component.UIRepeat.process(UIRepeat.java:522)
        at com.sun.faces.facelets.component.UIRepeat.encodeChildren(UIRepeat.java:926)
        at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1613)
        at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:273)
        at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:127)
        at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)

При этом условие рендеринга игнорируется, и интерпретатор EL жалуется на несуществующие свойства. Существует простое решение с использованием итератора h: dataTable с одним столбцом:

<h:dataTable value="#{rule.systemActions}" var="action">
        <c:set var="name" value="#{action.class.simpleName.toLowerCase()}" />
        <h:column>
            <h:panelGroup rendered="#{name == 'notification'}">
                    <h:outputLabel for="phone">Phone:</h:outputLabel>
                    <h:inputText value="#{action.phone}" id="phone" />
            </h:panelGroup>
            <h:panelGroup rendered="#{name == 'reminder'}">
              ...
            </h:panelGroup>
        </h:column>
  </h:dataTable>

Приветствие.

Яро

...