web-dev-qa-db-fra.com

Comment afficher l'index de ligne dans une table de données JSF

Dans une table de données JSF, je veux afficher l'index des lignes à côté des lignes ... comme:

Column A    Column B
1           xxx
2           yyy

J'ai pensé que je pourrais utiliser une variable el implicite comme # {rowIndex} mais cela ne fonctionne pas.

Une solution que j'ai trouvée consiste à créer une liaison pour la table de données et à utiliser la liaison comme:

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

mais cette solution est complexe et ne fonctionne pas bien lorsque j'ai plusieurs dataTables imbriqués dans une page.

Des idées sur la meilleure façon de résoudre ce problème?

24
Panagiotis Korros

La solution existante ne me semble pas mauvaise. Le rowIndex doit fonctionner dans les tables imbriquées tant que vous faites référence au modèle de la table imbriquée.

    <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>

Exemple de modèle:

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();
    }

}

Imbrication des données Les tableaux doivent généralement être évités - si vous ne faites pas attention (par exemple, faites-les enfants d'un formulaire), cela peut conduire à un O (N ^ 2) passer sur les enfants de la table pour chaque phase du cycle de vie d'une soumission (et il y a 6 phases dans le cycle de vie).


Pour quelque chose qui est externe au modèle, vous pouvez utiliser un simple compteur dans un bean géré:

public class RowCounter implements Serializable {

    private transient int row = 0;

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

}

Config:

<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>

Vue:

<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>

Cela fonctionne car le bean est de portée de demande et lié à un contrôle en lecture seule en dehors d'un formulaire. Cela ne fonctionnerait pas dans un dataTable imbriqué sauf si vous vouliez que le compteur de lignes soit global à la vue. Mais alors, je ne suis pas convaincu que l'index de ligne doit être fonction de la vue.

Pour un dataTable imbriqué, il serait préférable de fournir l'index de ligne à partir du bean de ligne. Cela vous donne plus de contrôle si vous décidez de faire des choses comme la pagination sur les ensembles de données.

16
McDowell

Cette solution a été publiée par Jamie Williams le CodeRanch . Il dit que cela fonctionne avec Tomahawk. J'utilise primefaces, qui le prend également en charge.

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

Dans RichFaces, il existe une solution similaire à celle de 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>
7
Yuri

Cela a fonctionné de moi

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

Je dépend simplement de la liste et de la position de var sur cette liste:

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