151 votes

Impossible de trouver le composant avec l'expression "foo" référencé à partir de "bar" - <f:ajax> contient id inconnu "foo" ne peut la trouver dans le cadre de la composante "bar"

Le code suivant est inspiré de PrimeFaces DataGrid + DataTable Tutoriels et les mettre dans un <p:tab> d'un <p:tabView> résidant dans un <p:layoutUnit> d'un <p:layout>. Ici est la partie intérieure du code (à partir de l' p:tab de la composante); la partie extérieure est trivial.

<p:tab title="Search">                        
    <h:form id="insTable">
        <p:dataTable var="lndInstrument" value="#{instrumentBean.instruments}">
            <p:column>
                <p:commandLink id="select" update="insTable:display" oncomplete="dlg.show()">
                    <f:setPropertyActionListener value="#{lndInstrument}" 
                                    target="#{instrumentBean.selectedInstrument}" />
                    <h:outputText value="#{lndInstrument.name}" />
                </p:commandLink>                                    
            </p:column>
        </p:dataTable>
        <p:dialog modal="true" widgetVar="dlg">
            <h:panelGrid id="display">
                <h:outputText value="Name:" />
                <h:outputText value="#{instrumentBean.selectedInstrument.name}" />
            </h:panelGrid>
        </p:dialog>                            
    </h:form>
</p:tab>

Lorsque je clique sur l' <p:commandLink>, le code s'arrête de travailler et donne le message:

Impossible de trouver le composant avec l'expression "insTable:affichage" référencé à partir de "onglets:insTable:sélectionner".

Quand j'ai essayer la même chose à l'aide de <f:ajax>, il échoue avec un message différent fondamentalement raconter la même:

<f:ajax> contient un id inconnu "insTable:affichage" ne peut la trouver dans le cadre de la composante "onglets:insTable:sélectionnez"

Comment est-il la cause et comment puis-je le résoudre?

331voto

BalusC Points 498232

Si un composant dont vous souhaitez pour référence par ajax processus/exécution/mise à jour/rendu n'est pas à l'intérieur de la même NamingContainer parent, alors vous devez le référencer à l'aide d'un absolu de l'IDENTIFIANT client à la place d'un parent ID de client.

NamingContainer des composants sont par exemple <h:form>, <h:dataTable>, <p:tabView>, <cc:implementation> (ainsi, tous les composants composites), etc. Vous les reconnaîtrez facilement en regardant le code HTML généré en sortie, de leur pièce d'identité sera ajouté au client généré ID de tous les composants enfants.

Un absolu de l'IDENTIFIANT client commence avec l' NamingContainer caractère de séparation, qui est par défaut :.

Pour les débutants qui n'ont pas mémorisé tout cela, un moyen facile de trouver la bonne ID de client est d'ouvrir la page dans le navigateur et de localiser l'élément HTML représenté par la JSF composante d'intérêt. C'est, dans votre cas particulier d' <h:panelGrid id="display"> un <table>. Si ce n'est pas par lui-même à l'intérieur d'un autre NamingContainer parent, alors l'ID du client est probablement juste <table id="display">. Comme il n'est pas à l'intérieur de la même NamingContainer des parents comme de l'endroit où vous êtes à l'exécution de la requête ajax, vous avez besoin de préfixe exactement ce client ID :.

<p:commandLink update=":display">

Mais si c'est par exemple à l'intérieur d'un <p:tabView id="tabs"><h:form id="form">, alors l'ID du client est susceptible <table id="tabs:form:display">.

<p:commandLink update=":tabs:form:display">

Tout cela est spécifié que "la recherche de l'expression" dans l' UIComponent#findComponent() javadoc:

Une expression de recherche se compose d'un identifiant (qui est parfaitement adaptée à l'encontre de la propriété id de UIComponent, ou une série de tels identifiants liés par l' UINamingContainer#getSeparatorChar la valeur du caractère. L'algorithme de recherche doit fonctionne de la façon suivante, si suppléant alogrithms peut être utilisé tant que le résultat final est le même:

  • Identifier l' UIComponent qui sera la base pour la recherche, en s'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é un "absolu" de recherche de l'expression), la base sera la racine de UIComponent de la composante de l'arbre. Le premier caractère de séparation sera éliminé, et le reste de l'expression de recherche sera traitée comme une "relative" à l'expression de recherche comme décrit ci-dessous.
    • Sinon, si c' UIComponent est NamingContainer il servira de base.
    • Sinon, recherchez jusqu'les parents de ce composant. Si un NamingContainer est rencontré, elle sera la base.
    • Sinon (si pas d' NamingContainer est rencontré) la racine UIComponent sera la base.
  • L'expression de recherche (éventuellement modifié dans l'étape précédente) est maintenant une "relative" à l'expression de recherche qui sera utilisé pour localiser le composant (le cas échéant) qui a un id qui correspond, dans le cadre de la composante de base. Le match se déroule comme suit:
    • Si l'expression de recherche est un identificateur simple, cette valeur est comparée à la propriété id, et puis, de manière récursive à travers les facettes et les enfants de la base UIComponent (sauf que, si un descendant NamingContainer est trouvé, son propre facettes et les enfants ne sont pas cherché).
    • Si l'expression de recherche comprend plus d'un identificateur séparés par le caractère de séparation, le premier identifiant est utilisé pour localiser un NamingContainer par les règles en la puce précédente. Ensuite, l' findComponent() méthode de NamingContainer sera appelé, en passant le reste de l'expression de recherche.

Notez que PrimeFaces adhère également la JSF spec, mais RichFaces utilise "certaines exceptions supplémentaires".

"reRender" utilise UIComponent.findComponent() algorithme (avec quelques exceptions) pour trouver le composant dans le composant de l'arbre.

Ces exceptions ne sont nulle part décrit en détail, mais il est connu que, par rapport Id composant (c'est à dire ceux qui ne sont pas en commençant par :) ne sont pas uniquement cherché dans le contexte de la plus proche parent NamingContainer, mais aussi dans tous les autres NamingContainer de composants dans le même point de vue (ce qui est relativement cher travail par la voie).

Si cela ne fonctionne toujours pas, vérifiez si vous n'utilisez pas <h:form prependId="false">. On va à l'échec cours de traitement de l'ajax soumettre et de rendu. Voir aussi cette question: JSF NamingContainer et UIForm avec prependId.

9voto

Daniel Points 20467

tout d'abord: pour autant que je sais placer dialogue à l'intérieur d'un tabview est une mauvaise pratique... il vaut mieux faire...

et maintenant, à votre question:

désolé, m'a fallu un certain temps pour obtenir exactement ce que vous avez voulu mettre en œuvre,

n'a à mon application web moi-même tout à l'heure, et il fonctionne

comme je l'ai dit avant de placer les p:boîte de dialogue à côté de la `p:tabView ,

laisser le p:boîte de dialogue que vous avez initialement suggéré :

<p:dialog modal="true" widgetVar="dlg">
    <h:panelGrid id="display">
        <h:outputText value="Name:" />
        <h:outputText value="#{instrumentBean.selectedInstrument.name}" />
    </h:panelGrid>
</p:dialog>   

et le p:commandlink devrait ressembler à ceci (tout ce que je fait est de changer la mise à jour de l'attribut)

<p:commandLink update="display" oncomplete="dlg.show()">
    <f:setPropertyActionListener value="#{lndInstrument}" 
        target="#{instrumentBean.selectedInstrument}" />
    <h:outputText value="#{lndInstrument.name}" />
</p:commandLink>  

les mêmes œuvres dans mon application web, et si cela ne fonctionne pas pour vous , alors je pense qu'il y a quelque chose de mal dans votre java bean code...

5voto

Lyrion Points 346

C'est parce que l'onglet est un conteneur de dénomination aswell... la mise à jour devrait être update="Search:insTable:display" Ce que vous pouvez faire est aswell il suffit de placer votre boîte de dialogue à l'extérieur de la forme et toujours à l'intérieur de la languette, alors il serait la suivante: update="Search:display"

0voto

Mr.J4mes Points 4868

Essayez de changer de update="insTable:display" de update="display". Je crois que vous ne pouvez pas le préfixe de l'id avec l'ID du formulaire, comme ça.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X