rich: проблемный размер строки - PullRequest
9 голосов
/ 08 января 2010

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

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

alt text

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

Может ли кто-нибудь предоставить для этого псевдокод?

Ура!

ОБНОВЛЕНИЕ 1: Я попытался установить rowspan столбцов слева в качестве размера списка или продуктов, а затем:

  • если продукты пустые (продуктов для компании пока нет), я печатаю две колонки. Я делаю это условно, устанавливая для атрибута rendered значение # {myFuncs: sizeOf (company.products)}
  • Если продукты> = 1, то я перебираю их с , и внутри этого цикла я вставляю два столбца (один для названия продукта и один для описания), и для каждого столбца имени продукта, кроме первого я установил для атрибута breakBefore значение # {! myFunc: firstProduct (company.products, product)} , которое оценивается как true для всех названий продуктов, кроме первого.

К сожалению, у меня это не сработало, потому что столбцы внутри a4j: repeat вообще не отображаются - не из-за визуализированного тега . Цикл правильный, потому что, если я печатаю стандартный текст, он появляется.

Есть ли способ достичь разряда строк, или я бьюсь головой о стену?

ОБНОВЛЕНИЕ 2: Вероятно, проблема связана с этой статьей , указывающей на различия между компонентами итерации, такими как и тегом . Первый происходит во время рендеринга, а второй - раньше, когда компоненты JSF помещаются в дерево компонентов страницы.

Я пытался получить rich: столбцы вне a4j: repeat, и они визуализировались (конечно, не так, как ожидалось, но они делают).

Ответы [ 3 ]

6 голосов
/ 18 января 2010

Вы можете сделать это без этих сложных 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>

Оказывает идеально для меня. Обратите внимание, что я использую Seam с Jboss Extended EL, который позволяет мне вызывать size () для коллекции. Если вы не используете это, вы можете использовать в качестве замены prs: collectionSize () или fn: length ().

Это также хорошо работает с контроллером данных Richfaces.

Надеюсь, это поможет.

D.

2 голосов
/ 08 января 2010

К сожалению, в компонентах JSF UIData отсутствует поддержка ряда строк. Лучшее, что вы можете сделать, это просто отобразить коллекцию продуктов в строке в том же . Вы можете перебрать его, используя другой UIData компонент, такой как h:dataTable (рендеринг <table>), t:dataList (рендеринг <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 с умом, чтобы он выглядел как строки.

0 голосов
/ 15 января 2010

ОК, основываясь на последнем обновлении, создал страницу, выполняя итерации, используя c: forEach (при построении дерева компонентов). Решение, которое я предоставляю, работает, но что-то не так, потому что:

  • Это занимает слишком много времени (~ 3 секунды, 100% ЦП для примерно 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>

...