Menu

Datagrid: selectedValues et rowValueColumnId

danyboy85
2007-06-19
2013-04-11
  • danyboy85

    danyboy85 - 2007-06-19

    Bonjour,

    Le problème que j'ai à expoeer est assez complexe, je vais essayer d'être le plus clair et le plus concis possible.

    J'utilise le composant <v:dataGrid> dans l'une de mes pages jsf. Cette page est detinée à afficher n'importe quelle type de données : une liste machines, de personnel, de sites de production, etc...

    J'ai donc mis en place un système permettant, à partir d'un fichier xml contenant le nombre de champs à afficher, leur nom..., de construire ma page jsf.

    En gros, cela implique le fait que je n'ai pas un nombre de <v:dataColumn> fixe, car je ne connais pas à l'avance le nombre de colonnes à afficher.

    J'ai donc une boucle "for" :

    <%
    for (int i=0; i<maListe.size(); i++) {
           GenericColumn gc = (GenericColumn)maListe.get(i);
    %>
       <v:dataColumn text="<%=gc.getLabel()%>"
                     value="<%=gc.getValue()%>" //--> getValue() contient une chaine de type "#{}"
                     width="<%=gc.getWidth()%>"
                     resizable="<%=gc.getResizable()%>"
                     sortListener="<%=gc.getSortlistener()%>"
                     alignment="<%=gc.getAlignment()%>"
                     visible="<%=gc.getVisible()%>"/>
    <%
    }
    %>

    Tout cela fonctionne parfaitement bien !!!

    Par contre, et j'en viens à mon problème, l'attribut "id" du <v:dataColumn> n'accepte pas les expressions, je n'ai donc pas renseigné cet attribut. J'ai pourtant besoin de spécifier cet attribut car je souhaite utiliser l'attribut "selectedValues" pour gérer la sélection de lignes. Or, cela implique que l'attribut "rowValueColumnId" soit renseigné avec l'id d'une colonne.
    Donc je suis bloqué...

    Malgré cela, je pense qu'il existe une solution mais je ne sais pas comment l'utiliser. En effet, si je renseigne l'attribut "selectedValues" sans renseigner l'attribute "rowValueColumnId", et bien lorsque je double-clique sur une ligne du tableau pour valider la sélection, Tomcat me retourne une page d'erreur avec l'erreur Rcfaces suivante : "'SelectedValues' attribute must contain an IIndexesModel if you do not specify 'rowValueColumnId' attribute".

    Je crois comprendre que je dois me touner vers "IIndexesModel" mais je ne sais pas ce que c'est.

    Auriez-vous une explication quant à sa mise en place, ou une autre solution?

    Merci d'avance.

    PS: désolé pour la longueur du post...

     
    • Olivier Oeuillot

      Salut,

      Je ne pense pas que l'usage de scriptlets comme tu le fais soit autorisé par la spec JSF ... (je suis même sure que non !)

      Ainsi, ton exemple marche parce que les enfants de DataGrid ne génèrent pas de rendu ...   Sinon tu désynchronises la vue JSF ... et attention les dégâts !

      Malheureusement, il n'y a pas de solution simple à ton problème (d'où je pense ta bidouille avec les scriplets) il faudrait peut-être voir du coté des facelets ...

      Sinon, un IIndexesModel est un objet qui contient un ensemble d'indexes.
      Aussi, il te faut binder le selectedValues sur un champ qui est de type IIndexesModel; aussi voila un exemple:

      <v:dataGrid  selectedValues="#{xxxx.selection}" >

      class Z {
         List indexesSelectionnés=new ArrayList();
         IIndexesModel indexesModel=new CollectionIndexesModel(indexesSelectionnés);

         public IIndexesModel getSelection() {
            return indexesModel;
         }
      }

      Tu retrouveras dans "indexesSelectionnés" des objets Integer qui contiendront les indices des lignes sélectionnées ...

      J'espère que c'est à peu prés clair  :-P

      Bonne journée,

      Olivier

       
    • danyboy85

      danyboy85 - 2007-06-20

      OK merci j'ai résussi à gérer la sélection de lignes !

      Pour ce qui est des scriptlets, je me doute que c'est de la bidouille mais bon ca marche nickel.

      Imagine, si on n'est obligé de spécifier un nombre de <v:dataColumn> fixe (en dur), on est vachement limité quand-même. Si on a 10000 listes différentes à afficher dans notre application, on est obligé de faire 10000 pages JSF différentes !?!?!?

      Avec ce que j'ai mis en place, j'ai une seule page qui gère toutes les listes de mon applictaion, avec le formulaire de saisie associé.

      Après, c'est clair que je ne sais pas comment c'est géré derrière donc on peut appeler ca de la bidouille, mais j'ai réalisé pas mal de tests sur ma page et ca fonctionne super bien.

      En fait j'utilise du jsp pur pour boucler les <v:dataColumn> (for (...) {...}) mais après j'utilise bien la syntaxe : value="#{maListe}" var="unElementDeLaListe" pour le contenu du dataGrid.

      En tout cas merci pour l'explication de IIndexesModel !

       
    • danyboy85

      danyboy85 - 2007-09-18

      Salut Olivier !

      Je viens de passer à JSF 1.2 et donc par la même occasion à RCFaces I2410.

      Je poste sur ce sujet existant car mon problème y est lié.

      Bon tout d'abord, j'ai toujours ma page JSF avec ma bidouille de scriplets pour pouvoir générer une page avec un nombre de <v:dataColumn> variable (voir ci-dessus).

      Mon problème c'est qu'avec la version I2140 de RCFaces, les expressions ne sont plus autorisés dans les attributs du <v:dataColumn>.

      Je concois que cela n'est en aucun cas une régression et je ne vais pas vous demander de "réautoriser" l'utilisation dex expressions JSP, cela parait évident.

      Par contre, je voulais savoir si vous (qui maîtrisez JSF et RCFaces mieux que moi) n'aviez pas une idée de la façon dont je pourrais faire pour générer un <v:dataGrid> avec un nombre de <v:dataColumn> variable (en gros faire une boucle sur <v:dataColumn> ou  quelque chose comme ca). Je souhaite réaliser ceci dans le but de pouvoir, sur une seule et unique page web, afficher n'importe quelle liste de données.

      Bonne journée

      Dany

       
      • Olivier Oeuillot

        Salut Dany,

        En effet la nouvelle façon de déclarer les attributs, invalide les expressions ${};
        j'en suis le premier surpris (Au premier abord, je n'avais pas lu cette subtilité), et j'ai du revoir de fond en comble l'AddressBook :-(

        Bref, il remarche, mais j'ai perdu des fonctionnalités au passage (par exemple, le titre du document)

        Sinon j'ai cru comprendre que les JSTL devaient fonctionner nettement mieux, et donc il y a peut-être une petite chance pour que les boucles du JSTL soient opérationnelles ???

        Tiens moi au courant, car ça m'intéresse aussi :-)

        Bonne après-midi,

        Olivier.

         
    • danyboy85

      danyboy85 - 2007-09-18

      J'ai essayé d'utiliser JSTL 1.2. Voici le code que j'obtiens :

      [CODE]
      <v:dataGrid doubleClickListener="#{dataGridManagedBean.selectLineAction}" border="0" id="datagrid_1" width="700" height="535" rows="10" var="genericData" value="#{dataGridManagedBean.genericRecordList}" selectable="true" selectionCardinality="?" selectedValues="#{dataGridManagedBean.im}" >

          <c:forEach items="#{dataGridManagedBean.genericHead.allCols}" var="col">
              <v:dataColumn   text="#{col.label}"
                              value="#{genericData.fields[0]}"
                              width="#{col.width}"
                              sortListener="#{col.sortlistener}"
                              resizable="#{col.resizable}"
                              alignment="#{col.alignment}"
                              visible="#{col.visible}"/>
          </c:forEach>

      </v:dataGrid>
      [/CODE]

      Mais il semble que le dataGrid est un peu perdu.

      Par exemple le tri
      d'une colonne me retourne une erreur du type :

      18 sept. 2007 14:33:37 org.rcfaces.renderkit.html.internal.service.DataGridService service
      GRAVE: Catch runtime exception !
      javax.el.PropertyNotFoundException: Target Unreachable, identifier 'col' resolved to null.

      Ensuite, comme tu l'auras remarqué, je spécifie l'indice des données à afficher en dur :

      "#{genericData.fields[0]}

      En fait j'affiche les mêmes données dans toutes les colonnes. Je ne vois pas où récupérer une variable indice et comment la noter :
      je ne pense pas que "#{genericData.fields[#{monIndice}]} fonctionne.

      En somme, avec JSTL ca ne me semble pas faisable.

      Sinon j'ai essayé de modifier la TLD du composant <v:dataGrid> pour autoriser les expressions dans les attributs, dans le genre <rtexprvalue>true</rtexprvalue>, mais j'obtiens cete erreur :

      Une erreur s'est produite à la ligne: 107 dans le fichier jsp: /tableau.jsp
      The method setText(ValueExpression) in the type DataColumnTag is not applicable for the arguments (String)

      (j'avoue c'est un peu barbare comme méthode...)

      Je n'ai pas d'autre piste pour l'instant...

       
      • Olivier Oeuillot

        >Sinon j'ai essayé de modifier la TLD du composant <v:dataGrid> pour autoriser les expressions dans les attributs, dans le genre <rtexprvalue>true</rtexprvalue>, mais j'obtiens cete erreur :

        Ben oui justement,  moi aussi :-)

        Et je l'ai vite remis <rtexprvalue>false</rtexprvalue> :-P

        Et un truc du style .... ?

        <c:forEach var="index" begin="1" end="#{dataGridManagedBean.genericHead.allCols.length???}">
              <v:dataColumn   text="#{dataGridManagedBean.genericHead.allCols[index].label}"
                                value="#{genericData.fields[index]}"   ..../>
        </c:forEach>

        Mais je pense que ca ne réglera pas le problème du plantage lors d'un appel AJAX, aussi je pense qu'il n'y a que les facelets qui peuvent t'aider ...

        Bon courage,

        Olivier.

         
    • danyboy85

      danyboy85 - 2007-09-19

      Bonjour Olivier !

      Excellente nouvelle, j'ai trouvé la solution !

      Je ne suis pas passé par les Facelets comme tu me l'a suggéré, j'ai fait encore plus simple.

      En fait j'ai tout simplement "bindé" mon composant <v:dataGrid> et je le construis côté serveur, dans mon ManagedBean.

      ***************************Côté serveur***********************************

      public class DataGridManagedBean {

          
           private List<GenericRecord> genericRecordList;
           private DataGridComponent dataGrid;
           ...

           public DataGridManagedBean() {
               
                ...

                dataGrid = new DataGridComponent("dataGrid1");
                List<GenericColumn> columnList = genericHead.getAllCols();
                for (int i=0; i<columnList.size(); i++) {
                     GenericColumn gc = columnList.get(i);
                     DataColumnComponent dataColumn =new DataColumnComponent("dataColumn" + i);
                     dataColumn.setText(gc.getLabel());
                     dataColumn.setWidth(gc.getWidth());
                     dataColumn.setResizable(gc.isResizable());
                     //dataColumn.addSortListener(new SortActionListener(gc.getSortlistener()));  /*ne fonctionne pas*/
                     
                     ValueExpression ve1 = FacesContext.getCurrentInstance().getApplication().getExpressionFactory().createValueExpression(FacesContext.getCurrentInstance().getELContext(), "#{genericData.fields[" + i + "]}", String.class);
                     dataColumn.setValue(ve1);
                     dataGrid.getChildren().add(dataColumn);
                  }
           }
      }

      ***************************Côté client***********************************

      <v:dataGrid doubleClickListener="#{dataGridManagedBean.selectLineAction}"
                  border="0"
                  id="datagrid1"
                  width="700"
                  height="535"
                  rows="10"
                  var="genericData"
                  value="#{dataGridManagedBean.genericRecordList}"
                  selectable="true"
                  selectionCardinality="?"
                  selectedValues="#{dataGridManagedBean.im}"
                  binding="#{dataGridManagedBean.dataGrid}"
      />

      Seul hic, je n'arrive pas à mettre en place le tri des colonnes. J'ai fait ceci :

      dataColumn.addSortListener(new SortActionListener("alpha"));

      mais lorsque je clique sur une entête de colonne pour la trier, j'ai l'erreur suivante :

      19 sept. 2007 10:03:33 org.rcfaces.renderkit.html.internal.service.DataGridService service
      GRAVE: Catch runtime exception !
      javax.faces.FacesException: Comparator of sortEvent is NULL !
              at org.rcfaces.core.internal.tools.GridServerSort$SortAction.<init>(GridServerSort.java:454)
              ...

      Voila, sinon cela fonctionne et c'est à priori la méthode la plus propre !

      Bonne journée

      Dany

       
      • Olivier Oeuillot

        Super Dany !

        Effectivement c'est le moyen le plus simple et propre !

        Essayes:

        dataColumn.addSortListener(new SortScriptListener(IHtmlRenderContext.JAVASCRIPT_TYPE, "alpha"));

        En espérant que cela fonctionne :-)

        Bonne journée,

        Olivier.

         
        • danyboy85

          danyboy85 - 2007-09-19

          Merci il n'y a plus d'erreur, mais le tri effectué est toujours un tri "alpha" même si je mets :

          dataColumn.addSortListener(new SortScriptListener(IHtmlRenderContext.JAVASCRIPT_TYPE, "number"));

          Rendu :

          1
          10
          11
          12
          2
          20
          21

           
          • Olivier Oeuillot

            Ha zut ... un petit BUG !

            Je viens de le corriger ... ce sera pour la I2412 :-P

            Merci pour l'info.

            Olivier.

             
    • danyboy85

      danyboy85 - 2007-09-19

      OK pas de souci !

       

Log in to post a comment.