2009-09-28 9 views
2

Quelle est la manière correcte d'avoir une case à cocher booléenne dans chaque ligne dans un JSF/RichFaces dataTable? J'ai essayé l'extrait suivant:Quelle est la bonne façon d'avoir une case à cocher booléenne dans un JSF/RichFaces `dataTable`?

<rich:dataTable id="customerList" 
       var="_customer" 
      value="#{customerList.resultList}" 
      rendered="#{not empty customerList.resultList}" > 
    <h:column> 
     <h:selectBooleanCheckbox 
      value="#{customerList.selectedCustomers[_customer.id]}" /> 
    </h:column> 
... 
</rich:dataTable> 

Je mis mon customerList d'avoir un Map<Integer, Boolean> selectedCustomers. Choses semblent pour bien fonctionner, sauf que, apparemment, la case à cocher est en train d'être mappé par un index de tri, pas réellement par l'ID, et cela me cause un problème. Par exemple, lorsque j'ouvre la page ci-dessus et cochez la case de la première ligne et que j'appuie sur le bouton «Supprimer», tout fonctionne correctement et la page est rechargée sans le client sélectionné. Mais si j'appuie sur "Actualiser" ou "Recharger" puis, (et accepter l'avertissement du navigateur de données renvoyées), le client qui est maintenant dans la première rangée est supprimé!

Que dois-je faire pour que la case à cocher soit liée à l'ID sélectionné uniquement?

Répondre

3

Si vous souhaitez uniquement gérer l'actualisation, consultez l'option redirect dans les règles de navigation.

<navigation-rule> 
    <display-name>navBack</display-name> 
    <from-view-id>/navBack.jsp</from-view-id> 
    <navigation-case> 
     <from-outcome>navTo</from-outcome> 
     <to-view-id>/navTo.jsp</to-view-id> 
     <redirect /> 
    </navigation-case> 
    </navigation-rule> 

Si vous souhaitez également manipuler des boîtiers à boutons et à plusieurs fenêtres, lisez la suite.

Vous pouvez le détecter à l'aide d'un champ masqué et d'un artefact au niveau de la ligne. Fondamentalement, vous vérifiez l'id émis au client contre l'id reçu quand le formulaire est soumis.

public class SafeRow { 
    private final String rowId; 
    private String rowIdClient; 
    private String name; 
    private boolean delete; 

    public SafeRow(String name) { 
    this(); 
    this.name = name; 
    } 

    public SafeRow() { 
    rowId = UUID.randomUUID().toString(); 
    } 

    public String getRowId() { return rowId; }  
    public void setRowId(String rowIdClient) { this.rowIdClient = rowIdClient; } 

    public boolean isStateConsistent() { 
    return rowId.equals(rowIdClient); 
    } 

    public String getName() { return name; } 
    public void setName(String name) { this.name = name; } 

    public boolean isDelete() { return delete; } 
    public void setDelete(boolean delete) { this.delete = delete; } 
} 

Les données de table:

public class SafeUpdateBean { 
    private final List<SafeRow> data = new ArrayList<SafeRow>(); 

    public SafeUpdateBean() { 
    data.add(new SafeRow("Bill")); 
    data.add(new SafeRow("Ben")); 
    data.add(new SafeRow("Sue")); 
    } 

    public List<SafeRow> getData() { return data; } 

    public String deleteSelected() { 
    Iterator<SafeRow> all = data.iterator(); 
    while (all.hasNext()) { 
     SafeRow row = all.next(); 
     if (!row.isStateConsistent()) { 
     System.err.println("Caught inconsistency on " + row.getRowId()); 
     } else if (row.isDelete()) { 
     all.remove(); 
     } 
    } 
    return null; 
    } 
} 

La vue:

<h:form> 
    <h:dataTable value="#{safeUpdateBean.data}" var="row"> 
    <h:column> 
     <h:inputHidden value="#{row.rowId}" /> 
     <h:selectBooleanCheckbox value="#{row.delete}" /> 
     <h:outputText value="#{row.name}" /> 
    </h:column> 
    </h:dataTable> 
    <h:commandButton value="delete selected" 
    action="#{safeUpdateBean.deleteSelected}" /> 
</h:form> 

Ce code de démonstration utilise un haricot simple session, mais nous espérons qu'il est clair comment vous pouvez l'adapter à quelque chose de plus sensible. Ce n'est pas la seule chose que vous pourriez faire - vous pourriez effectuer une soumission de formulaire en double plus générale, par exemple. Les frameworks tiers tels que Seam ajoutent également de la gestion pour ce genre de choses.

+0

Merci. Bien que je ne sois pas très clair comment cela fonctionne (ou ce qui rendra l'état de ligne de sécurité incohérent), la note sur la soumission de formulaire en double et Seam est utile. Je vais essayer Seam's ''. –

+0

Lorsque le formulaire est soumis, les lignes seront décodées par index. Puisque l'identifiant dans le champ caché ne correspond plus à l'identifiant de cet index sur le serveur, la logique métier sait qu'il y a un problème. Le fait de faire fonctionner l'id setter/getter avec différentes variables membres est utilisé pour le déterminer. – McDowell

+0

Très bien, +1, merci. Mais serait-ce plus simple si je n'utilisais que des cases à cocher normales en HTML, et les prenais sous la forme d'une liste contenant les identifiants? –

Questions connexes