rich: проблема с datatable rowspan

Мне нужно создать rich: dataTable (или даже extended) со следующими функциями:

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

alt text

Я до сих пор не понял, как это сделать с вложенной таблицей (во всех примерах я нашел, что вложенная таблица имеет те же столбцы, что и главная таблица). Предположительно, мне нужно играть с 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>