【问题标题】:How to display the row index in a JSF datatable如何在 JSF 数据表中显示行索引
【发布时间】:2010-09-22 19:46:39
【问题描述】:

在 JSF 数据表中,我想在行旁边显示行索引...例如:

Column A    Column B
1           xxx
2           yyy

我认为我可以使用像 #{rowIndex} 这样的隐式 el 变量,但这不起作用。

我找到的一个解决方案是为数据表创建一个绑定并使用如下绑定:

<h:dataTable var="item" value="#{controller.items}" binding="#{controller.dataTable}">
    <h:column>#{controller.dataTable.rowIndex}</h:column>
    <h:column>value</h:column>
</h:dataTable>

但是当我在一个页面中有许多嵌套的数据表时,这个解决方案很复杂并且效果不佳。

关于如何以更好的方式解决此问题的任何想法?

【问题讨论】:

标签: jsf datatable


【解决方案1】:

此解决方案由 Jamie Williams 在CodeRanch 上发布。他说它适用于战斧。我正在使用 primefaces,它也支持它。

<t:dataTable rowIndexVar="row" value="#{someBean.value}">  
    <h:column>  
        <h:outputText value="#{row + 1}"/>  
    </h:column>  
</t:dataTable>

【讨论】:

  • Ursula 的评论:“感谢您使用 rowIndexVar 的解决方案。我正在使用 JSF 1.2 和 myFaces,它只能在 row+1 &lt;h:outputText value="#{row+1}"/&gt; 没有空格的情况下工作”
【解决方案2】:

现有的解决方案在我看来并不坏。只要您引用嵌套表的模型,rowIndex 就应该在嵌套表中工作。

    <h:dataTable border="1" value="#{nestedDataModel}" var="nested">
        <h:column>
            <h:dataTable border="1" value="#{nested}" var="item">
                <h:column>
                    <h:outputText value="#{nested.rowIndex}" />
                </h:column>
                <h:column>
                    <h:outputText value="#{item}" />
                </h:column>
            </h:dataTable>
        </h:column>
    </h:dataTable>

示例模型:

public class NestedDataModel extends DataModel implements Serializable {

    private List<List<String>> nestedDataModel = populateModel();
    private int index;

    private List<List<String>> populateModel() {
        List<List<String>> list = new ArrayList<List<String>>();
        for(int x=0; x<3; x++) {
            List<String> nestedTableData = new ArrayList<String>();
            for(int y=0; y<3; y++) {
                nestedTableData.add("Foo x="+x+" y="+y);
            }
            list.add(nestedTableData);
        }
        return list;
    }

    @Override
    public int getRowCount() {
        return nestedDataModel.size();
    }

    @Override
    public Object getRowData() {
        List<String> list = nestedDataModel.get(index);
        return new ListDataModel(list);
    }

    @Override
    public int getRowIndex() {
        return index;
    }

    @Override
    public Object getWrappedData() {
        return nestedDataModel;
    }

    @Override
    public boolean isRowAvailable() {
        return index >= 0 && index < nestedDataModel.size();
    }

    @Override
    public void setRowIndex(int arg0) {
        index = arg0;
    }

    @Override
    public void setWrappedData(Object arg0) {
        throw new UnsupportedOperationException();
    }

}

通常应避免嵌套数据表 - 如果您不小心(例如,将它们设为表单的子级),这可能会导致 O(N^2) 在生命周期的每个阶段通过表子级提交(生命周期中有 6 个阶段)。


对于模型外部的东西,您可以在托管 bean 中使用一个简单的计数器:

public class RowCounter implements Serializable {

    private transient int row = 0;

    public int getRow() {
        return ++row;
    }

}

配置:

<managed-bean>
    <managed-bean-name>rowCounter</managed-bean-name>
    <managed-bean-class>tablerows.RowCounter</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
</managed-bean>

查看:

<f:view>
    <h:dataTable border="1" value="#{tableDataBean.tableDataModel}"
        var="rowBean">
        <h:column>
            <h:outputText value="#{rowCounter.row}" />
        </h:column>
        <h:column>
            <h:outputText value="#{rowBean}" />
        </h:column>
    </h:dataTable>
</f:view>

这是可行的,因为 bean 是请求范围的,并且绑定到表单外的只读控件。除非您希望行计数器对视图是全局的,否则它在嵌套的 dataTable 中不起作用。但是,我不相信行索引应该是视图的函数。

对于嵌套数据表,最好从行 bean 提供行索引。如果您也决定对数据集进行分页等操作,它会给您更多的控制权。

【讨论】:

  • 不错。为什么从 JSF 数据表中获取行号这么复杂?维护 JSF 的人是否憎恨所有其他开发人员,并且他们故意让 JSF 变得困难?
【解决方案3】:

在 RichFaces 中有一个类似于 Brent 的解决方案:

<rich:dataTable value="#{backingBean.list}" var="v" rowKeyVar="index">
    <rich:column>
        <f:facet name="header">Index</f:facet>
        <h:outputText value="#{index + 1}" />
    </rich:column>
    <rich:column>
        <f:facet name="header">Name</f:facet>
        <h:outputText value="#{v.name}" />
    </rich:column>
</rich:dataTable>

【讨论】:

    【解决方案4】:

    这对我有用

    <h:dataTable var="item" value="#{controller.items}">
        <h:column>#{controller.items.indexOf(item)}</h:column>
        <h:column>value</h:column>
    </h:dataTable>
    

    【讨论】:

    • 这个解决方案有一个问题:它只有在你有一个合适的equals方法时才有效,否则你总是会得到-1。而且每个对象都必须不同。如果您在数据结构中有多个相等对象,您将始终获得第一个位置(如果它是一个列表)。
    【解决方案5】:

    我只是依赖列表和 var 在这个列表中的位置:

    <h:column>
              <f:facet name="header">#</f:facet>
              #{bean.listValue.indexOf(varObject)+1}
    </h:column>
    

    【讨论】:

      【解决方案6】:

      自 JSF 2.0(2009 年引入)以来,视图中的当前 UIComponent 实例可通过隐式 EL 变量 #{component} 获得。另见What exactly is #{component} in EL?

      &lt;h:dataTable&gt; 标签由实现NamingContainerUIData 组件支持。因此,在&lt;h:dataTable&gt; 上下文中的任何位置使用#{component.namingContainer} 将为您提供具体的UIData 实例,通常具有HtmlDataTable 类的风格。

      <h:dataTable value="#{['one', 'two', 'three']}" var="item">
          <h:column>This is the `UIData` component: #{component.namingContainer}</h:column>
      </h:dataTable>
      

      jakarta.faces.component.html.HtmlDataTable@cafebabe
      jakarta.faces.component.html.HtmlDataTable@cafebabe
      jakarta.faces.component.html.HtmlDataTable@cafebabe

      UIData 类又具有getRowIndex() 方法,所以这就足够了:

      <h:dataTable value="#{['one', 'two', 'three']}" var="item">
          <h:column>Row index: #{component.namingContainer.rowIndex + 1}</h:column>
      </h:dataTable>
      

      1
      2
      3

      请注意它是从零开始的,因此是 + 1

      不需要binding 或第 3 方标签或任何自定义支持 bean 逻辑。

      【讨论】:

        猜你喜欢
        • 2011-02-16
        • 1970-01-01
        • 2012-04-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-06
        • 2012-04-25
        • 1970-01-01
        相关资源
        最近更新 更多