Récursivité dans JSF (c:forEach vs ui:repeat)
Je suis en train de construire une arborescence de navigation via la récursivité dans le programme JSF. J'ai défini un navigationNode
composant:
<composite:interface>
<composite:attribute name="node" />
</composite:interface>
<composite:implementation>
<ul>
<ui:repeat value="#{navigationTreeBean.getChildrenForNode(cc.attrs.node)}" var="child">
<li><navigation:navigationNode node="#{child}" /></li>
</ui:repeat>
</ul>
</composite:implementation>
Mon arbre est déclarée comme suit:
rootNode = new DefaultMutableTreeNode(new NodeData("Dashboard", "dashboard.xhtml"), true);
DefaultMutableTreeNode configurationsNode = new DefaultMutableTreeNode(new NodeData("Configurations", "configurations.xhtml"), true);
rootNode.add(configurationsNode);
J'appelle composante par:
<nav:navigationNode node="#{rootNode}" />
Le problème est, il en résulte StackOverflowError
.
Il y a quelques références à la construction de la récursivité dans JSF (par exemple, c:forEach vs ui:repeat dans Facelets). Le problème commun semble être le mélange de la construction et de rendre les composants/tags. Dans mon cas:
- Mon composite composant est en fait une balise, qui est exécutée lorsque l'arbre est construit
- ui:repeat est un réel JSF élément, qui est évalué lorsque l'arbre est rendu
Est l'enfant du composant navigation:navigationNode
réellement traitée avant la ui:repeat
composant? Si oui, quel objet est-il de l'aide pour #{child}
? Est-il nul (ne semble pas si)? Le problème est ici que le composant enfant est effectivement créé, sans même se soucier de l'interface utilisateur:répéter et à chaque fois un nouveau composant enfant est créé, même si elle n'est pas forcément voulu?
La c:forEach vs ui:repeat dans Facelets article a une section distincte pour cette (récursivité). La suggestion est d'utiliser c:forEach
à la place. J'ai essayé ceci, cependant, c'est toujours de me donner la même StackOverflowError
, avec différentes traces que je ne peut pas donner un sens.
Je sais que nous pouvons également créer des composants en étendant UIComponent
, mais cette approche (l'écriture de code html dans le code Java) semble laid. Je préfère utiliser MVC de style ou de modèles. Cependant, si il n'y a pas d'autres moyens, dois-je mettre en œuvre cette sorte de récursivité comme UIComponent à la place?
OriginalL'auteur Tuukka Mustonen | 2010-08-16
Vous devez vous connecter pour publier un commentaire.
JSF intégré dans déclarative balises sont mal adaptés pour la manipulation de ce genre de récursivité. JSF construit avec un état de la composante de l'arbre qui est conservé entre les demandes. Si la vue est rétabli dans la demande, l'état d'affichage peuvent ne pas refléter les changements dans le modèle.
Je favoriserais un impératif approche. Vous avez deux options:
binding
attribut de lier un contrôle (par exemple, une certaine forme de panneau) à un support de haricot qui fournit laUIComponent
instance et de ses enfants - vous écrire du code pour instancier leUIComponent
et ajouter tout ce que les enfants vous le souhaitez. Voir les spécifications dubinding
attribut contrat.UIComponent
; unRenderer
; un tag gestionnaire; les méta-données des fichiers (rayez - vous faire une partie ou l'ensemble de ces en fonction de ce que vous faites et comment et dans quelle version de JSF).Peut-être une autre option est de prendre un 3ème contrôle du parti qui fait déjà cela.
Mise à JOUR:
Si l'on est à l'aide de la très utile OmniFaces bibliothèque (vous devriez, si vous ne l'avez pas déjà), il est le
<o:arbre>
qui n'a pas de génération html que ce soit, mais a été conçu spécifiquement pour la usecases comme ça.EDIT:
Voici une approche guidée par le modèle qui n'implique pas l'écriture de composants personnalisés ou backing-bean-composante issue des arbres. C'est un peu laid.
Les Facelets vue:
Le managed bean:
Un nœud de l'arborescence:
De sortie:
J'ai toujours mordre la balle et écrire une arborescence personnalisée de contrôle.
PrimeFaces/supports utilise jQuery themeroller framework CSS. La moyenne CSS designer doit déjà être au courant.
Mustonen - la dynamique de la composante de l'arbre qui sous-tend le cadre de l'ACI fait ce que vous voulez difficile, et il serait une rupture de changement pour le supprimer.
McDowell: Merci de fournir un exemple de code avec votre réponse. Sur la base de cette base itérative semble hackyish mais je trouve également intéressant 🙂 Jamais pensé à ça. Je ressens cela ne fonctionne que lorsque l'arbre est construit dans le bon ordre. Cependant, ce ne serait pas un problème. @ BalusC: Merci pour le pointeur vers le themeroller. J'ai peur c'est trop simple, cependant. Chaque composant a sa propre feuille de style CSS, vous ne personnalisez pas dans themeroller. Cependant, je vais prendre un autre regard sur ce que, dans mon premier coup d'oeil, je n'ai pas trouver comment remplacer le composant CSS spécifique.
Tentez votre algorithme avec un arbre avec un seul enfant par nœud. Les trois rendra tout sur le même niveau.
OriginalL'auteur McDowell
J'ai eu un problème similaire(StackOverflowException) lors de la migration de notre application à partir de jsf 1.x à 2.x. Si vous êtes à l'aide de la c:forEach approche de la jsf récursivité, assurez-vous d'utiliser le nouvel espace de noms pour jstl de base.
Utilisation
au lieu de
Voici le modèle que nous utilisons, adaptés à votre scénario.
client.xhtml
récursive.xhtml
La question ne mentionne StackoverflowException à l'aide de c:forEach, qui est ce que j'ai obtenu avec les invalides de l'espace de noms. J'ai mis à jour la réponse à inclure le code complet de la récursion.
Cela semble au moins être la récursivité par opposition à l'autre solution qui semble être juste la construction d'une énorme liste de nœuds avec des drapeaux pour indiquer si le nœud est une feuille ou pas. Je ne pense pas que l'autre solution aurait toute la profondeur comme la récursivité doit.
OriginalL'auteur Anonymous