2010-09-14 9 views
4

J'ai un problème étrange avec la balise <ui:repeat>. Même pour mon exemple très simple, les liaisons de valeurs dans les composants de répétition imbriqués ne fonctionnent pas comme prévu.JSF: liaisons de valeurs à l'intérieur de l'interface utilisateur imbriquée: répétition

J'ai simple Facelet comme ceci:

<h:body> 
<h:form> 
<ui:repeat value="#{sandbox.rows}" var="row"> 
    <ui:repeat value="#{row.columns}" var="column"> 
     <h:outputText value="#{column.value}" /> 
     <h:selectBooleanCheckbox value="#{column.value}" /> 
    </ui:repeat> 
    <br/> 
</ui:repeat> 

<h:commandButton action="#{sandbox.refresh}" value="Refresh" /> 
</h:form> 
</h:body> 

et une classe Sandbox:

@Component 
@Scope("request") 
public class Sandbox { 

    public static class Row { 
     private List<Column> columns = Arrays.asList(new Column(), new Column()); 
     public List<Column> getColumns() { 
      return columns; 
     } 
    } 

    public static class Column { 
     private boolean value; 
     public void setValue(boolean value) { 
      this.value = value; 
     } 
     public boolean getValue() { 
      return this.value; 
     } 
    } 

    public List<Row> rows = Arrays.asList(new Row(), new Row()); 

    public List<Row> getRows() { 
     return rows; 
    } 

    public void refresh() { 
     rows.get(0).getColumns().get(0).setValue(true); 
     System.err.println("refresh clicked"); 
    } 
} 

Alors mon Facelet boucles sur les "lignes" dans bac à sable, ce qui a un certain nombre de « colonnes ", qui a chacun une valeur. Pour chaque colonne de ce type, la valeur est imprimée et un <h:selectBooleanCheckbox> avec la valeur qui lui est liée est généré.

Lorsque je charge la page, toutes les valeurs sont affichées comme étant fausses et toutes les cases ne sont pas cochées. Maintenant, cliquer sur refresh est supposé modifier la valeur de la première colonne de la première ligne à true. Cependant, je reçois la sortie suivante:

 
true [ ] false [ ] 
false [ ] false [ ] 

En d'autres termes, les <h:outputText> affiche comme vrai, mais la case à cocher est pas cochée. Certes, je suis autorisé à changer le modèle dans la phase d'application invoke et cela devrait être reflété lors du rendu de la vue?

Si je supprime un niveau d'imbrication, il n'y en a qu'un <ui:repeat>, tout fonctionne comme prévu: la case à cocher est cochée et la valeur est affichée comme vraie. Cela semble donc avoir quelque chose à voir avec le composant UIRepeat. En fait, il semble que UIRepeat ait un traitement spécial pour quand il est imbriqué dans un autre UIRepeat. D'après ce que je comprends, UIRepeat redessine essentiellement le même composant plusieurs fois. Entre chaque appel à rendre, il charge l '"état" (value, localValue, submittedValue) de tous les composants enfants implémentant EditableValueHolder depuis une mappe interne (saisie sur l'ID réel du composant rendu). J'ai essayé de mettre des points de rupture quand cela se produit pour suivre quelle valeur est insérée dans la carte des états sauvegardés, mais c'est vraiment un gâchis, car les méthodes saveChildState et restoreChildState sont appelées à un moment gazillion.

Des idées? Puis-je faire à ce sujet différemment? Ce dont j'ai vraiment besoin, c'est de pouvoir rendre une table qui se développe dynamiquement à la fois horizontalement et verticalement, contenant des cases à cocher, des champs de saisie, etc. J'ai regardé <h:dataTable> mais je crois que ça ne marchera pas dans ce cas.

Répondre

6

Problème intéressant. Je peux reproduire ceci avec Mojarra 2.0.3. C'est certainement un problème dans l'économie d'état de ui:repeat. Je l'ai signalé comme issue 1807 aux gars de Mojarra. Cela marche bien quand la boucle externe est c:forEach.

+0

Ma boucle externe ne peut pas être un c: forEach, car dans ma vraie application, tout est intégré dans un composant composite. – waxwing

+0

Encore une fois, je suis étonné par vos connaissances et votre serviabilité. Merci! Je vais suivre avec impatience ce problème pour voir ce qu'ils disent. – waxwing

+0

Encore, ça * peut * être. Quel est le problème que vous avez avec? Edit: pas de problème, de rien. – BalusC