Указать условный рендеринг элемента внутри <ui: repeat>? <C: if>, похоже, не работает

Я пытаюсь условно создать пользовательский список, используя <ui:repeat>. При каждом вхождении -1 в качестве значения item в списке мне нужно добавить разрыв строки.

Я попытался использовать <c:if> внутри <ui:repeat> для этого, но он не работает. Он всегда оценивает false.

<ul>      
    <ui:repeat value="#{topics.list}" var="topicId" >
        <li>#{topicId}</li>
        <c:if test="#{topicId eq -1}">  <br/>  </c:if>
    </ui:repeat>
</ul>

Возможно ли это?

Ответ 1

Не с тегами JSTL, нет. Они запускаются во время просмотра времени просмотра, а не во время просмотра рендеринга. Вы можете визуализировать его следующим образом, когда JSF создает представление, теги JSTL запускаются снизу сначала, а результат - это чистое дерево компонентов JSF. Затем, когда JSF отображает представление, компоненты JSF работают сверху вниз, а результат - это куча HTML. Таким образом, JSTL и JSF не синхронизируются, как вы ожидали от кодирования. В настоящий момент ваш <c:if> работает, #{topicId} недоступен в области.

Вместо использования <c:if> вам нужно указать условие в атрибуте rendered интересующего компонента JSF. Поскольку вы на самом деле нет, вы можете обернуть его в <ui:fragment>.

<ul>      
    <ui:repeat value="#{topics.list}" var="topicId" >
        <li>#{topicId}</li>
        <ui:fragment rendered="#{topicId eq -1}"><br/></ui:fragment>
    </ui:repeat>
</ul>

Альтернативы <h:panelGroup>

<h:panelGroup rendered="#{topicId eq -1}"><br/></h:panelGroup>

или в вашем конкретном случае <h:outputText escape="false">

<h:outputText value="&lt;br/&gt;" escape="false" rendered="#{topicId eq -1}" />

поскольку оба они также не выдают ничего больше на вывод HTML, если не указаны атрибуты стороны клиента.

См. также:


Несвязанный к конкретной проблеме, это неправильное место для <br/>. Он будет игнорироваться любым веб-браузером в соответствии с спецификацией HTML. Разве вы не хотите, чтобы это было внутри <li>? Или лучше, дайте ему class и пусть CSS даст ему margin-bottom.