Rechercher dans la sortie HTML l'ID client réel
Vous devez regarder dans la sortie HTML générée pour trouver le bon ID client. Ouvrez la page dans le navigateur, faites un clic droit et voir la source . Recherchez la représentation HTML du composant JSF qui vous intéresse et prenez-la id
comme ID client. Vous pouvez l'utiliser de manière absolue ou relative en fonction du conteneur de dénomination actuel. Voir le chapitre suivant.
Note: si elle arrive à contenir l' itération index comme :0:
, :1:
, etc (parce qu'il est à l' intérieur d' un composant itérer), alors vous devez réaliser que la mise à jour d' un cycle d'itération spécifique ne sont pas toujours pris en charge. Voir le bas de la réponse pour plus de détails à ce sujet.
Mémorisez les NamingContainer
composants et donnez-leur toujours un identifiant fixe
Si un composant que vous souhaitez référencer par ajax process / execute / update / render se trouve dans le même NamingContainer
parent, alors référencez simplement son propre ID.
<h:form id="form">
<p:commandLink update="result"> <!-- OK! -->
<h:panelGroup id="result" />
</h:form>
Si ce n'est pas le même NamingContainer
, vous devez le référencer à l'aide d'un ID client absolu. Un ID client absolu commence par le NamingContainer
caractère de séparation, qui est par défaut :
.
<h:form id="form">
<p:commandLink update="result"> <!-- FAIL! -->
</h:form>
<h:panelGroup id="result" />
<h:form id="form">
<p:commandLink update=":result"> <!-- OK! -->
</h:form>
<h:panelGroup id="result" />
<h:form id="form">
<p:commandLink update=":result"> <!-- FAIL! -->
</h:form>
<h:form id="otherform">
<h:panelGroup id="result" />
</h:form>
<h:form id="form">
<p:commandLink update=":otherform:result"> <!-- OK! -->
</h:form>
<h:form id="otherform">
<h:panelGroup id="result" />
</h:form>
NamingContainer
composants sont par exemple <h:form>
, <h:dataTable>
, <p:tabView>
, <cc:implementation>
(ainsi, tous les composants composites), etc. Vous les reconnaissent facilement en regardant la sortie HTML généré, leur carte d' identité sera préfixé au client ID généré de tous les composants de l' enfant. Notez que lorsqu'ils n'ont pas d'ID fixe, JSF utilisera un ID généré automatiquement au j_idXXX
format. Vous devez absolument éviter cela en leur donnant un identifiant fixe. Les OmniFacesNoAutoGeneratedIdViewHandler
peuvent être utiles à cet égard pendant le développement.
Si vous savez trouver le javadoc de l'objet UIComponent
en question, vous pouvez également simplement vérifier s'il implémente l' NamingContainer
interface ou non. Par exemple, HtmlForm
(la balise UIComponent
derrière <h:form>
) montre qu'elle implémente NamingContainer
, mais HtmlPanelGroup
(la balise UIComponent
derrière <h:panelGroup>
) ne l'affiche pas, donc elle ne l'implémente pas NamingContainer
. Voici le javadoc de tous les composants standard et voici le javadoc de PrimeFaces .
Résoudre votre problème
Donc dans votre cas de:
<p:tabView id="tabs"><!-- This is a NamingContainer -->
<p:tab id="search"><!-- This is NOT a NamingContainer -->
<h:form id="insTable"><!-- This is a NamingContainer -->
<p:dialog id="dlg"><!-- This is NOT a NamingContainer -->
<h:panelGrid id="display">
La sortie HTML générée de <h:panelGrid id="display">
ressemble à ceci:
<table id="tabs:insTable:display">
Vous devez prendre exactement cela id
comme ID client, puis préfixer avec :
pour une utilisation dans update
:
<p:commandLink update=":tabs:insTable:display">
Référencement extérieur à include / tagfile / composite
Si ce lien de commande est à l'intérieur d'un include / tagfile et que la cible est à l'extérieur de celui-ci, et que vous ne connaissez donc pas nécessairement l'ID du conteneur de dénomination parent du conteneur de dénomination actuel, vous pouvez le référencer dynamiquement via UIComponent#getNamingContainer()
comme ceci:
<p:commandLink update=":#{component.namingContainer.parent.namingContainer.clientId}:display">
Ou, si ce lien de commande est à l'intérieur d'un composant composite et que la cible est à l'extérieur de celui-ci:
<p:commandLink update=":#{cc.parent.namingContainer.clientId}:display">
Ou, si le lien de commande et la cible sont à l'intérieur du même composant composite:
<p:commandLink update=":#{cc.clientId}:display">
Voir aussi Obtenir l'ID du conteneur de dénomination parent dans le modèle pour l'attribut de rendu / mise à jour
Comment ça marche sous les couvertures
Tout cela est spécifié comme "expression de recherche" dans le UIComponent#findComponent()
javadoc :
Une expression de recherche se compose soit d'un identificateur (qui correspond exactement à la propriété id de a UIComponent
, soit d'une série d'identificateurs liés par la UINamingContainer#getSeparatorChar
valeur du caractère. L'algorithme de recherche doit fonctionner comme suit, bien que d'autres algorithmes puissent être utilisés tant que le le résultat final est le même:
- Identifiez le
UIComponent
qui sera la base de la recherche, en vous arrêtant dès que l'une des conditions suivantes est remplie:
- Si l'expression de recherche commence par le caractère séparateur (appelé expression de recherche "absolue"), la base sera la racine
UIComponent
de l'arborescence des composants. Le caractère séparateur de tête sera supprimé et le reste de l'expression de recherche sera traité comme une expression de recherche "relative" comme décrit ci-dessous.
- Sinon, s'il
UIComponent
s'agit d'un, NamingContainer
il servira de base.
- Sinon, recherchez les parents de ce composant. Si un
NamingContainer
est rencontré, ce sera la base.
- Sinon (si aucun
NamingContainer
n'est rencontré), la racine UIComponent
sera la base.
- L'expression de recherche (éventuellement modifiée à l'étape précédente) est maintenant une expression de recherche "relative" qui sera utilisée pour localiser le composant (le cas échéant) qui a un identifiant qui correspond, dans la portée du composant de base. Le match se déroule comme suit:
- Si l'expression de recherche est un identifiant simple, cette valeur est comparée à la propriété id, puis récursivement à travers les facettes et les enfants de la base
UIComponent
(sauf que si un descendant NamingContainer
est trouvé, ses propres facettes et enfants ne sont pas recherchés).
- Si l'expression de recherche comprend plusieurs identifiants séparés par le caractère de séparation, le premier identifiant est utilisé pour localiser un
NamingContainer
par les règles de la puce précédente. Ensuite, la findComponent()
méthode NamingContainer
sera appelée, en passant le reste de l'expression de recherche.
Notez que PrimeFaces adhère également à la spécification JSF, mais RichFaces utilise «quelques exceptions supplémentaires» .
"reRender" utilise un UIComponent.findComponent()
algorithme (avec quelques exceptions supplémentaires) pour trouver le composant dans l'arborescence des composants.
Ces exceptions supplémentaires ne sont nulle part décrites en détail, mais il est connu que les ID de composants relatifs (c'est-à-dire ceux qui ne commencent pas par :
) sont non seulement recherchés dans le contexte du parent le plus proche NamingContainer
, mais également dans tous les autres NamingContainer
composants de la même vue (ce qui est relativement travail coûteux d'ailleurs).
Ne jamais utiliser prependId="false"
Si tout cela ne fonctionne toujours pas, vérifiez si vous n'utilisez pas <h:form prependId="false">
. Cela échouera pendant le traitement de la soumission et du rendu ajax. Voir aussi cette question connexe: UIForm avec prependId = "false" breaks <f: ajax render> .
Référencement d'un cycle d'itération spécifique de composants itératifs
Pendant longtemps, il n'a pas été possible de référencer un élément itéré spécifique dans des composants itératifs comme <ui:repeat>
et <h:dataTable>
comme ceci:
<h:form id="form">
<ui:repeat id="list" value="#{['one','two','three']}" var="item">
<h:outputText id="item" value="#{item}" /><br/>
</ui:repeat>
<h:commandButton value="Update second item">
<f:ajax render=":form:list:1:item" />
</h:commandButton>
</h:form>
Cependant, depuis que Mojarra 2.2.5 a <f:ajax>
commencé à le supporter (il a simplement cessé de le valider; ainsi, vous ne feriez plus jamais face à l'exception mentionnée dans la question; un autre correctif d'amélioration est prévu pour cela plus tard).
Cela ne fonctionne pas encore dans les versions actuelles de MyFaces 2.2.7 et PrimeFaces 5.2. Le support pourrait venir dans les futures versions. En attendant, votre meilleur pari est de mettre à jour le composant itératif lui-même, ou un parent au cas où il ne rendrait pas le HTML, comme <ui:repeat>
.
Lorsque vous utilisez PrimeFaces, pensez aux expressions de recherche ou aux sélecteurs
PrimeFaces Search Expressions vous permet de référencer des composants via des expressions de recherche d'arborescence de composants JSF. JSF a plusieurs intégrés:
@this
: composant actuel
@form
: parent UIForm
@all
: document entier
@none
: rien
PrimeFaces a amélioré cela avec de nouveaux mots clés et la prise en charge des expressions composites:
@parent
: composant parent
@namingcontainer
: parent UINamingContainer
@widgetVar(name)
: composant identifié par donné widgetVar
Vous pouvez également mélanger ces mots - clés dans les expressions composites tels que @form:@parent
, @this:@parent:@parent
, etc.
Les sélecteurs PrimeFaces (PFS) comme dans @(.someclass)
vous permettent de référencer des composants via la syntaxe du sélecteur CSS jQuery. Par exemple, référencer des composants ayant tous une classe de style commune dans la sortie HTML. Ceci est particulièrement utile au cas où vous auriez besoin de faire référence à «un grand nombre» de composants. Cela nécessite uniquement que les composants cibles aient tous un ID client dans la sortie HTML (fixe ou généré automatiquement, peu importe). Voir aussi Comment fonctionnent les sélecteurs PrimeFaces comme dans update = "@ (. MyClass)"?