JSTL в Jsf2 Facelets ... имеет смысл?


Я хотел бы вывести немного кода Facelets условно.

для этой цели теги JSTL, похоже, работают нормально:

<c:if test="${lpc.verbose}">
    ...
</c:if>

однако, я не уверен, что это лучшая практика? Есть ли другой способ достичь моей цели?

3 149

3 ответа:

введение

JSTL <c:xxx> теги taghandlers и они выполняются во время посмотреть время сборки, в то время как JSF <h:xxx> теги компоненты пользовательского интерфейса и они выполняются во время вид отображения времени.

обратите внимание, что из собственного JSF <f:xxx> и <ui:xxx> теги только те, которые делают не продлить от UIComponent также являются taghandlers, например <f:validator>, <ui:include>,<ui:define> и т. д. Те, которые простираются от UIComponent также JSF компонентов пользовательского интерфейса, например,<f:param>,<ui:fragment>,<ui:repeat> и т. д. Из компонентов JSF UI только id и binding атрибуты также оцениваются во время построения представления. Таким образом, приведенный ниже ответ относительно жизненного цикла JSTL также относится к id и binding атрибуты компонентов JSF.

время сборки представления - это тот момент, когда файл XHTML/JSP должен быть проанализирован и преобразован в дерево компонентов JSF который затем сохраняется как UIViewRoot на FacesContext. Время визуализации представления - это тот момент, когда дерево компонентов JSF собирается генерировать HTML, начиная с UIViewRoot#encodeAll(). Так: JSF компонентов пользовательского интерфейса и тегов JSTL не работает в синхронизации, как вы ожидаете от кодирования. Вы можете визуализировать его следующим образом: JSTL сначала запускается сверху вниз, создавая дерево компонентов JSF, затем очередь JSF снова запускается сверху вниз, создавая вывод HTML.

<c:forEach> vs <ui:repeat>

например, эта разметка Facelets повторяет 3 элемента с помощью <c:forEach>:

<c:forEach items="#{bean.items}" var="item">
    <h:outputText id="item_#{item.id}" value="#{item.value}" />
</c:forEach>

...создает во время просмотра сборки три отдельных <h:outputText> компоненты в дереве компонентов JSF, примерно представленные следующим образом:

<h:outputText id="item_1" value="#{bean.items[0].value}" />
<h:outputText id="item_2" value="#{bean.items[1].value}" />
<h:outputText id="item_3" value="#{bean.items[2].value}" />

...которые, в свою очередь, индивидуально генерируют свой HTML-вывод во время просмотра render time:

<span id="item_1">value1</span>
<span id="item_2">value2</span>
<span id="item_3">value3</span>

обратите внимание, что вам необходимо вручную обеспечить уникальность идентификаторов компонентов и что они также являются оценивается во время построения представления.

в то время как эта разметка Facelets повторяется над 3 элементами с помощью <ui:repeat>, который является компонентом пользовательского интерфейса JSF:

<ui:repeat id="items" value="#{bean.items}" var="item">
    <h:outputText id="item" value="#{item.value}" />
</ui:repeat>

...уже заканчивается как есть в дереве компонентов JSF, где тот же самый <h:outputText> компонент находится во время просмотра рендерингаповторно для создания вывода HTML на основе текущего цикла итерации:

<span id="items:0:item">value1</span>
<span id="items:1:item">value2</span>
<span id="items:2:item">value3</span>

отметим, что <ui:repeat> как NamingContainer компонент уже обеспечили уникальность идентификатора клиента на основе индекса итерации; также невозможно использовать EL в id атрибут дочерних компонентов таким образом, как он также оценивается во время построения представления во время #{item} доступно только во время просмотра время рендеринга. Же самое верно и для h:dataTable и подобных компонентов.

<c:if>/<c:choose> vs rendered

в качестве другого примера, эта разметка Facelets условно добавляет разные теги с помощью <c:if> (вы также можете использовать <c:choose><c:when><c:otherwise> для это):

<c:if test="#{field.type eq 'TEXT'}">
    <h:inputText ... />
</c:if>
<c:if test="#{field.type eq 'PASSWORD'}">
    <h:inputSecret ... />
</c:if>
<c:if test="#{field.type eq 'SELECTONE'}">
    <h:selectOneMenu ... />
</c:if>

...в случае type = TEXT добавить только <h:inputText> компонент в дереве компонентов JSF:

<h:inputText ... />

пока это Facelets разметка:

<h:inputText ... rendered="#{field.type eq 'TEXT'}" />
<h:inputSecret ... rendered="#{field.type eq 'PASSWORD'}" />
<h:selectOneMenu ... rendered="#{field.type eq 'SELECTONE'}" />

...в конечном итоге точно так же, как и выше, в дереве компонентов JSF независимо от условия. Таким образом, это может оказаться в "раздутом" дереве компонентов, когда у вас их много, и они фактически основаны на "статической" модели (т. е. field никогда не меняется, по крайней мере, в области видимости). Кроме того, вы можете столкнуться с EL проблемы когда вы имеете дело с подклассами с дополнительными свойствами в Mojarra до версии 2.2.7.

<c:set> vs <ui:param>

они не заменимы. Элемент <c:set> задает переменную в области EL, которая доступна только после расположение тега во время построения представления, но в любом месте представления во время отображения представления. Элемент <ui:param> передает переменную EL в шаблон Facelet, включенный через <ui:include>,<ui:decorate template> или <ui:composition template>. Более старые версии JSF имели ошибки, при которых <ui:param> переменная также доступна за пределами рассматриваемого шаблона Facelet, на это никогда не следует полагаться.

The <c:set> без

использовать

<h:panelGroup rendered="#{lpc.verbose}">
  ...
</h:panelGroup>

извините за отдельный ответ, но я не могу комментировать ответы выше.

для переключател-подобного выхода вы можете использовать переключатель от primefaces-extensions.