rich: проблема с datatable rowspan
Мне нужно создать rich: dataTable (или даже extended) со следующими функциями:
У меня есть компания класса, имеющая коллекцию объектов продукта. Я хочу показать следующую таблицу:
Я до сих пор не понял, как это сделать с вложенной таблицей (во всех примерах я нашел, что вложенная таблица имеет те же столбцы, что и главная таблица). Предположительно, мне нужно играть с rowspans в первых двух столбцах, но я все еще не нашел путь.
может ли кто-нибудь предоставить псевдокод для этого?
Ура!
обновление 1: Я попытался установить rowspan столбцы слева, как размер списка или продуктов, а затем :
- если продукты пусты (пока нет продуктов для компании), я печатаю два столбца. Я делаю это условно, устанавливая их вынесено для #{myFuncs: sizeOf (company.продукты)}
- если продукты >= 1, то я повторяю их с и внутри этого цикла я вставляю два столбца (один для названия продукта и один для описания), и для каждого столбца имени продукта, кроме первого, я устанавливаю breakBefore до #{ !myFunc: firstProduct (company.продукты, изделия)}, который вычисляет значение true для всех названий продуктов, кроме первого один.
к сожалению, это не сработало для меня, потому что столбцы внутри a4j:повторять не появляются вовсе не из-за вынесено тег. Цикл правильный, потому что если я печатаю стандартный текст else, он появляется.
есть ли способ достичь rowspan, или я бьюсь головой о стену?
обновление 2: Проблема, вероятно, связана с этим статьи, С указанием различия между компонентами итерации, такими как и тег . Первый происходит во время рендеринга, а второй работает Раньше, когда компоненты JSF помещаются в дерево компонентов страницы.
Я попытался получить rich: столбцы за пределами a4j: повторите, и они будут визуализированы (конечно, не так, как ожидалось, но они это делают).
3 ответов
вы можете сделать это без этих сложных forEachs. Вам просто нужно воспользоваться subTable и rowKeyVar.
например:
<rich:dataTable
value="#{backingBean.companyList}"
rows="100"
var="company">
<f:facet name="header">
<rich:columnGroup>
<rich:column>Company Name</rich:column>
<rich:column>Company Email</rich:column>
<rich:column>Product Name</rich:column>
<rich:column>Product Email</rich:column>
</rich:columnGroup>
</f:facet>
<rich:subTable value="#{company.products}" var="product" rowKeyVar="rowKey">
<rich:column rowspan="#{company.products.size()}" rendered="#{rowKey eq 0}">
#{company.name}
</rich:column>
<rich:column rowspan="#{company.products.size()}" rendered="#{rowKey eq 0}">
#{company.email}
</rich:column>
<rich:column>
#{product.name}
</rich:column>
<rich:column>
#{product.email}
</rich:column>
</rich:subTable>
</rich:dataTable>
делает идеально для меня. Обратите внимание, что я использую шов, который имеет JBoss Extended EL, который позволяет мне вызывать size() в коллекции. Если вы не используете это, вы можете использовать prs:collectionSize() или fn:length() в качестве замены.
Это также хорошо работает с richfaces datascroller.
Надежда эта помощь.
Д.
к сожалению, в JSF нет поддержки rowspan UIData
компоненты. Лучше всего, что вы могли бы сделать, это просто отобразить коллекцию продуктов в то же самое row. Вы можете перебирать его, используя другой UIData
компонент, таких как h:dataTable
(renders <table>
),t:dataList
(renders <ul>
) или a4j:repeat
(ничего не отображает, вам нужно использовать, например,<br/>
после каждого пункта).
полу-псевдо на основе основных компонентов JSF:
<h:dataTable value="#{bean.companies}" var="company">
<h:column>
<h:outputText value="#{company.name}" />
</h:column>
<h:column>
<h:outputText value="#{company.email}" />
</h:column>
<h:column>
<h:dataTable value="#{company.products}" var="product">
<h:column>
<h:outputText value="#{product.name}" />
</h:column>
</h:dataTable>
</h:column>
<h:column>
<h:dataTable value="#{company.products}" var="product">
<h:column>
<h:outputText value="#{product.description}" />
</h:column>
</h:dataTable>
</h:column>
</h:dataTable>
используйте CSS умным способом так что похоже rowspans.
OK, основываясь на последнем обновлении, создал страницу, выполняющую итерации с помощью c: forEach (при построении дерева компонента). Решение, которое я предоставляю, работает, но что-то в этом не так, потому что:
- это занимает слишком много времени (~3 секунды 100% CPU для около 20 компаний и 200 продуктов). Я подозреваю, что это связано с тем, что цикл for c: forEach по существу строит огромное дерево компонентов, которое должно быть отображено, а не начальные подходы где дерево компонентов было намного меньше.
- Я думаю, что мне придется перестроить все дерево компонентов для каждого изменения данных, а не просто перерисовывать его.
в любом случае, код. То, что я сделал что-то вроде этого (не проверял ниже, но вы получите картину. Обратите внимание, что итерация внутри rich: dataTable по существу игнорируется):
<rich:dataTable width="70%" id="applicantsTable" rows="100"
rowClasses="applicant_row" columnClasses="col"
value="#{backingBean.companyList}" var="company">
<f:facet name="header">
<rich:column>
<h:outputText styleClass="headerText" value="Company Name" />
</rich:column>
<rich:column>
<h:outputText styleClass="headerText" value="Company Email" />
</rich:column>
<rich:column>
<h:outputText styleClass="headerText" value="Product Name" />
</rich:column>
<rich:column>
<h:outputText styleClass="headerText" value="Product Email" />
</rich:column>
</f:facet>
<c:forEach items="#{backingBean.companyList}" var="c_company">
<c:if test="#{prs:collectionSize(c_company.products)> 0}">
<rich:column breakBefore="true"
rowspan="#{prs:collectionSize(c_company.products)}">
<h:outputText value="#{c_company.name}" />
</rich:column>
<rich:column
rowspan="#{prs:collectionSize(c_company.products)}">
<h:outputText value="#{c_company.email}" />
</rich:column>
<c:forEach items="#{c_company.products}" var="c_product">
<!-- This if clause is just to determine the breakBefore attribute -->
<c:if test="#{c_company.products[0] == c_product}">
<rich:column>
<h:outputText value="#{c_product.name}" />
</rich:column>
</c:if>
<c:if test="#{c_company.products[0] != c_product}">
<rich:column breakBefore="true" styleClass="internal_cell">
<h:outputText value="#{c_product.name}" />
</rich:column>
</c:if>
<rich:column styleClass="internal_cell">
<h:outputText value="#{c_product.email}" />
</rich:column>
</c:forEach>
</c:if>
</c:forEach>