Suchen Sie in der HTML-Ausgabe nach der tatsächlichen Client-ID
Sie müssen in der generierten HTML-Ausgabe nachsehen, um die richtige Client-ID herauszufinden. Öffnen Sie die Seite im Browser, klicken Sie mit der rechten Maustaste und zeigen Sie die Quelle an . Suchen Sie die HTML-Darstellung der interessierenden JSF-Komponente und nehmen Sie sie id
als Client-ID. Sie können es je nach aktuellem Namenscontainer absolut oder relativ verwenden. Siehe folgendes Kapitel.
Hinweis: Wenn es Iteration Index enthalten geschieht wie :0:
, :1:
usw. (weil es nicht in einem Iterieren Komponente ist), dann müssen Sie feststellen , dass eine bestimmte Iteration Runde Aktualisierung wird nicht immer unterstützt. Weitere Informationen hierzu finden Sie unten in der Antwort.
Merken Sie sich NamingContainer
Komponenten und geben Sie ihnen immer eine feste ID
Wenn sich eine Komponente, auf die Sie mit ajax process / execute / update / render verweisen möchten, innerhalb desselben NamingContainer
übergeordneten Elements befindet , verweisen Sie einfach auf ihre eigene ID.
<h:form id="form">
<p:commandLink update="result"> <!-- OK! -->
<h:panelGroup id="result" />
</h:form>
Wenn es nicht dasselbe ist NamingContainer
, müssen Sie es mit einer absoluten Client-ID referenzieren. Eine absolute Client-ID beginnt mit dem NamingContainer
Trennzeichen, das standardmäßig verwendet wird :
.
<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
Komponenten sind zum Beispiel <h:form>
, <h:dataTable>
, <p:tabView>
, <cc:implementation>
(also alle Verbundbauteile), etc. Sie sie , indem man die generierten HTML - Ausgabe leicht erkennen, ihre ID zu der generierten Client - ID aller untergeordneten Komponenten vorangestellt werden. Beachten Sie, dass JSF eine automatisch generierte ID im j_idXXX
Format verwendet , wenn sie keine feste ID haben . Sie sollten dies unbedingt vermeiden, indem Sie ihnen einen festen Ausweis geben. Die OmniFacesNoAutoGeneratedIdViewHandler
können dabei während der Entwicklung hilfreich sein.
Wenn Sie wissen, dass Sie das Javadoc des UIComponent
betreffenden Objekts finden , können Sie dort auch einfach überprüfen, ob es die NamingContainer
Schnittstelle implementiert oder nicht. Zum Beispiel zeigt das HtmlForm
(das UIComponent
hintere <h:form>
Tag), dass es implementiert ist NamingContainer
, aber das HtmlPanelGroup
(das UIComponent
hintere <h:panelGroup>
Tag) zeigt es nicht an, so dass es nicht implementiert wird NamingContainer
. Hier ist das Javadoc aller Standardkomponenten und hier ist das Javadoc von PrimeFaces .
Lösen Sie Ihr Problem
Also in Ihrem Fall von:
<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">
Die generierte HTML-Ausgabe von <h:panelGrid id="display">
sieht folgendermaßen aus:
<table id="tabs:insTable:display">
Sie müssen genau das id
als Client-ID verwenden und dann ein Präfix :
für die Verwendung in update
:
<p:commandLink update=":tabs:insTable:display">
Verweise außerhalb von include / tagfile / compos
Befindet sich diese Befehlsverknüpfung innerhalb einer Include- / Tag-Datei und das Ziel außerhalb davon, und Sie kennen daher nicht unbedingt die ID des übergeordneten Namenscontainers des aktuellen Namenscontainers, können Sie sie dynamisch UIComponent#getNamingContainer()
wie folgt referenzieren :
<p:commandLink update=":#{component.namingContainer.parent.namingContainer.clientId}:display">
Oder wenn sich diese Befehlsverknüpfung innerhalb einer zusammengesetzten Komponente befindet und sich das Ziel außerhalb dieser befindet:
<p:commandLink update=":#{cc.parent.namingContainer.clientId}:display">
Oder wenn sich sowohl die Befehlsverknüpfung als auch das Ziel in derselben zusammengesetzten Komponente befinden:
<p:commandLink update=":#{cc.clientId}:display">
Siehe auch ID des übergeordneten Namenscontainers in der Vorlage für das Attribut render / update abrufen
Wie funktioniert es unter der Decke?
Dies alles wird als angegeben „Such Ausdruck“ in der UIComponent#findComponent()
javadoc :
Ein Suchausdruck besteht entweder aus einem Bezeichner (der genau mit der ID-Eigenschaft von a übereinstimmt UIComponent
, oder einer Reihe solcher Bezeichner, die durch den UINamingContainer#getSeparatorChar
Zeichenwert verknüpft sind . Der Suchalgorithmus sollte wie folgt funktionieren, obwohl alternative Alogrithmen verwendet werden können, solange der Endergebnis ist das gleiche:
- Identifizieren Sie die
UIComponent
Basis für die Suche, indem Sie anhalten, sobald eine der folgenden Bedingungen erfüllt ist:
- Wenn der Suchausdruck mit dem Trennzeichen (als "absoluter" Suchausdruck bezeichnet) beginnt, ist die Basis die Wurzel
UIComponent
des Komponentenbaums. Das führende Trennzeichen wird entfernt und der Rest des Suchausdrucks wird wie unten beschrieben als "relativer" Suchausdruck behandelt.
- Andernfalls, wenn dies
UIComponent
ist eine NamingContainer
wird als Grundlage dienen.
- Suchen Sie andernfalls die übergeordneten Elemente dieser Komponente. Wenn a
NamingContainer
angetroffen wird, ist es die Basis.
- Andernfalls (wenn keine gefunden
NamingContainer
wird) ist die Wurzel UIComponent
die Basis.
- Der Suchausdruck (möglicherweise im vorherigen Schritt geändert) ist jetzt ein "relativer" Suchausdruck, der verwendet wird, um die Komponente (falls vorhanden) mit einer übereinstimmenden ID im Bereich der Basiskomponente zu lokalisieren. Das Match wird wie folgt durchgeführt:
- Wenn der Suchausdruck ein einfacher Bezeichner ist, wird dieser Wert mit der Eigenschaft id verglichen und dann rekursiv durch die Facetten und untergeordneten Elemente der Basis
UIComponent
(außer wenn ein Nachkomme NamingContainer
gefunden wird, werden seine eigenen Facetten und untergeordneten Elemente nicht durchsucht).
- Wenn der Suchausdruck mehr als eine durch das Trennzeichen getrennte Kennung enthält, wird die erste Kennung verwendet, um eine
NamingContainer
nach den Regeln im vorherigen Aufzählungspunkt zu lokalisieren . Dann wird die findComponent()
Methode hierfür NamingContainer
aufgerufen, wobei der Rest des Suchausdrucks übergeben wird.
Beachten Sie, dass PrimeFaces auch die JSF-Spezifikation einhält, RichFaces jedoch "einige zusätzliche Ausnahmen" verwendet .
"reRender" verwendet einen UIComponent.findComponent()
Algorithmus (mit einigen zusätzlichen Ausnahmen), um die Komponente im Komponentenbaum zu finden.
Diese zusätzlichen Ausnahmen werden nirgends im Detail beschrieben, aber es ist bekannt, dass relative Komponenten-IDs (dh solche, die nicht mit beginnen :
) nicht nur im Kontext des nächsten übergeordneten Elements gesucht werden NamingContainer
, sondern auch in allen anderen NamingContainer
Komponenten in derselben Ansicht (was relativ ist) teurer Job übrigens).
Benutze niemals prependId="false"
Wenn dies alles immer noch nicht funktioniert, überprüfen Sie, ob Sie es nicht verwenden <h:form prependId="false">
. Dies schlägt während der Verarbeitung des Ajax-Submit und -Renderings fehl. Siehe auch diese verwandte Frage: UIForm mit prependId = "false" bricht <f: ajax render> .
Referenzieren einer bestimmten Iterationsrunde iterierender Komponenten
Es war für lange Zeit nicht möglich , eine bestimmte iteriert Artikel in Iterieren Komponenten wie zu verweisen <ui:repeat>
und in <h:dataTable>
etwa so:
<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>
Seit Mojarra 2.2.5 hat es jedoch <f:ajax>
begonnen, es zu unterstützen (es hat einfach aufgehört, es zu validieren; daher würden Sie nie mehr mit der in der Frage genannten Ausnahme konfrontiert sein; eine weitere Verbesserung ist später geplant).
Dies funktioniert nur in den aktuellen Versionen von MyFaces 2.2.7 und PrimeFaces 5.2 noch nicht. Die Unterstützung wird möglicherweise in zukünftigen Versionen verfügbar sein. In der Zwischenzeit ist es am besten, die iterierende Komponente selbst oder ein übergeordnetes Element zu aktualisieren, falls es kein HTML rendert <ui:repeat>
.
Berücksichtigen Sie bei der Verwendung von PrimeFaces Suchausdrücke oder Selektoren
Mit PrimeFaces-Suchausdrücken können Sie Komponenten über JSF-Komponentenbaum- Suchausdrücke referenzieren. JSF hat mehrere eingebaute:
@this
: aktuelle Komponente
@form
: Elternteil UIForm
@all
: gesamtes Dokument
@none
: nichts
PrimeFaces hat dies durch neue Schlüsselwörter und Unterstützung für zusammengesetzte Ausdrücke erweitert:
@parent
: übergeordnete Komponente
@namingcontainer
: Elternteil UINamingContainer
@widgetVar(name)
: Komponente wie durch gegeben identifiziert widgetVar
Sie können auch diese Keywords in zusammengesetzten Begriffen wie mischen @form:@parent
, @this:@parent:@parent
usw.
Mit PrimeFaces Selectors (PFS) wie in @(.someclass)
können Sie Komponenten über die jQuery CSS-Selektorsyntax referenzieren. Verweisen auf Komponenten mit einer gemeinsamen Stilklasse in der HTML-Ausgabe. Dies ist besonders hilfreich, wenn Sie auf "viele" Komponenten verweisen müssen. Dies setzt nur voraus, dass die Zielkomponenten alle eine Client-ID in der HTML-Ausgabe haben (fest oder automatisch generiert, spielt keine Rolle). Siehe auch Wie funktionieren PrimeFaces-Selektoren wie in update = "@ (. MyClass)"?
context.getViewRoot().findComponent(":inputform" + UINamingContainer.getSeparatorChar(context) + "inputtext" );
Geben Sie auch den xhtml-Code an.prependId="false"
meinem Tag gerettet.Zuallererst: Soweit ich weiß, ist es eine schlechte Praxis, einen Dialog in einer Tab-Ansicht zu platzieren. Nehmen Sie ihn besser heraus.
und nun zu deiner frage:
Entschuldigung, ich habe einige Zeit gebraucht, um genau das zu bekommen, was Sie implementieren wollten.
habe gerade an meiner Web-App selbst gearbeitet, und es funktioniert
Wie ich bereits sagte, platzieren Sie den p: -Dialog außerhalb des `p: tabView.
Verlassen Sie den Dialog p: wie ursprünglich vorgeschlagen:
und der p: Befehlslink sollte so aussehen (alles was ich getan habe ist das Update Attribut zu ändern)
das gleiche funktioniert in meiner Web-App, und wenn es bei Ihnen nicht funktioniert, dann stimmt wohl etwas in Ihrem Java-Bean-Code nicht ...
quelle
update="Search:insTable:display"
Dies liegt daran, dass die Registerkarte auch ein Namenscontainer ist. Ihr Update sollte lauten. Sie können Ihren Dialog auch außerhalb des Formulars und immer noch innerhalb der Registerkarte platzieren. Dann wäre es:update="Search:display"
quelle
Versuchen Sie Änderung
update="insTable:display"
anupdate="display"
. Ich glaube, Sie können der ID keine solche Formular-ID voranstellen.quelle
Ich weiß, dass dies bereits eine großartige Antwort von BalusC hat, aber hier ist ein kleiner Trick, mit dem ich den Container dazu bringe, mir die richtige clientId mitzuteilen .
Hier ist ein Codebeispiel, da meine Worte es möglicherweise nicht am besten beschreiben.
Entfernen Sie das fehlerhafte Update innerhalb dieser Komponente
Fügen Sie eine Komponente innerhalb der Komponente der ID hinzu, die Sie mit einem fehlgeschlagenen Update aktualisieren möchten
Klicken Sie auf diese Seite und zeigen Sie den Fehler an. Der Fehler lautet: javax.servlet.ServletException: Die Komponente für den Ausdruck "BogusUpdate", auf den über die Registerkarten verwiesen wird, kann nicht gefunden werden : insTable: BogusButton
Die richtige zu verwendende clientId wäre dann fett und die ID des Zielcontainers (in diesem Fall anzeigen).
quelle