JSF 2 ui:repeat: группировать каждые n элементов внутри div

Учитывая коллекцию, которую я хочу расположить на странице следующим образом:

<!-- Group 0 -->
<div style="float:left;">
    <div><!-- Item 0 --></div>
    <div><!-- Item 1 --></div>

    <!-- ... -->

    <div><! -- Item n - 1 --></div>
</div>
<!-- Group 1 -->
<div style="float:left;">
    <div><!-- Item n     --></div>
    <div><!-- Item n + 1 --></div>

    <!-- ... -->

    <div><! -- Item 2n - 1 --></div>
</div>

<!-- ... -->

<!-- Group g -->
    <div><!-- Item gn     --></div>
    <div><!-- Item gn + 1 --></div>

    <!-- ... -->

    <div><! -- Item (g + 1)n - 1 --></div>
</div>

Есть ли какой-то трюк, который я могу использовать, чтобы сделать это внутри ui:repeat или с помощью какой-либо другой техники, предпочтительно кроме создания пользовательского компонента?


person Distortum    schedule 07.05.2012    source источник


Ответы (2)


Вы можете проверить текущий раунд цикла по атрибуту varStatus и вывести посредника </div><div style="float: left;"> при необходимости.

Например. каждые 3 предмета:

<div style="float: left;">
    <ui:repeat value="#{bean.list}" var="item" varStatus="loop">
        <h:outputText value="&lt;/div&gt;&lt;div style='float: left;'&gt;" escape="false" rendered="#{not loop.first and loop.index % 3 == 0}" />
        <div>#{item}</div>
    </ui:repeat>
</div>

Обратите внимание, что это невозможно обернуть как обычный HTML внутри <h:panelGroup>, потому что это приведет к неправильно сформированному XML, следовательно, <h:outputText escape="false"> с ними как сущностями XML.


Обновите в соответствии с комментариями, вот альтернативный подход, в котором <div> определены только один раз, что, вероятно, менее запутанно:

<ui:repeat value="#{bean.list}" var="item" varStatus="loop">
    <h:outputText value="&lt;div style='float: left;'&gt;" escape="false" rendered="#{loop.index % 3 == 0}" />
    <div>#{item}</div>
    <h:outputText value="&lt;/div&gt;" escape="false" rendered="#{loop.last or (loop.index + 1) % 3 == 0}" />
</ui:repeat>
person BalusC    schedule 07.05.2012
comment
Вы заметили &lt;/div&gt; в выходном тексте? Это закрывает группу. Я считаю четное количество открывающих и закрывающих тегов div, а не нечетное число. - person BalusC; 07.05.2012
comment
Да, я вижу, что вы сделали, поэтому я внимательно, долго смотрел на это и еще не редактировал. Это умно. Проблема в том, что вам нужно открыть первую группу. - person Distortum; 07.05.2012
comment
Ах, список может быть пустым? Затем заверните все в <h:panelGroup rendered="#{not empty bean.list}">. Ставьте при необходимости все в состав, чтобы скрыть всю многословность. - person BalusC; 07.05.2012

Если возможно, я бы разбил сбор на стороне сервера:

<ui:repeat value="#{groups}" var="group">
  <div style="float:left;">
    <ui:repeat value="#{group.items}" var="item">
      <div>#{item.content}</div>
    </ui:repeat>
  </div>
</ui:repeat>

другой вариант может быть (не тестировался, в частности, не уверен в поведении размера):

<ui:repeat value="#{items}" var="group" varStatus="status" step="n">
  <div style="float:left;">
    <ui:repeat value="#{items}" var="item" offset="#{status.index}" size="#{status.index + n}">
      <div>#{item.content}</div>
    </ui:repeat>
  </div>
</ui:repeat>

РЕДАКТИРОВАТЬ: вторая версия заменена

person mrembisz    schedule 07.05.2012
comment
+1 за ваше первое решение, потому что это сработает, и несколько минут назад я подумал о чем-то подобном. Мой план состоял в том, чтобы использовать пользовательскую функцию для применения группировки. Однако я не уверен, что ваше второе решение сработает. По крайней мере, любая IDE его ненавидит. - person Distortum; 07.05.2012
comment
Последний работает только в JSP, но не в Facelets, потому что это синтаксически недопустимый XML. Но в JSP у вас нет тегов <ui:xxx>, только <c:forEach> и <c:if>. - person BalusC; 07.05.2012
comment
Ваш обновленный второй пример не приводит к желаемому выводу HTML. - person BalusC; 07.05.2012
comment
Использовал другой подход. Теперь все должно быть в порядке. - person mrembisz; 07.05.2012
comment
Это не работает, если список имеет размер %n!=0 элементов. Тогда size вложенного цикла будет больше фактического оставшегося размера. - person BalusC; 07.05.2012
comment
Может быть, но вопрос предполагает размер % n == 0. Однако код легко адаптировать. - person mrembisz; 07.05.2012
comment
Я использовал второе решение, работает как шарм, только во втором пользовательском интерфейсе: повтор, размер должен быть n : size=n - person Hossein; 15.02.2015