it-swarm.com.de

Grundlegendes zu PrimeFaces-Prozessen / -Updates und JSF f: Ajax-Ausführungs- / Renderattributen

Was genau sind process und update in PrimeFaces p:commandXxx Komponenten und execute und render im f:ajax Tag?

Welches funktioniert zum Zeitpunkt der Validierung? Was bewirkt das Attribut update, anstatt den Wert der Komponente vom Back-End aus zu aktualisieren? Binden die Attribute process den Wert an das Modell? Was genau machen @this, @parent, @all und @form in beiden Attributen?

Das folgende Beispiel funktioniert gut, aber ich bin ein wenig verwirrt in grundlegenden Konzepten.

<p:commandButton process="@parent"
                 update="@form"
                 action="#{bean.submit}" 
                 value="Submit" />
176
Shardendu

_<p:commandXxx process>_ _<p:ajax process>_ _<f:ajax execute>_

Das Attribut process ist serverseitig und kann nur UIComponent implementieren EditableValueHolder (Eingabefelder) oder ActionSource (Befehlsfelder). Das Attribut process teilt JSF mithilfe einer durch Leerzeichen getrennten Liste von Client-IDs mit, welche Komponenten genau während des gesamten JSF-Lebenszyklus verarbeitet werden müssen, wenn (Teil-) Formulare gesendet werden.

JSF wendet dann die Anforderungswerte an (Ermitteln des HTTP-Anforderungsparameters basierend auf der eigenen Client-ID der Komponente und Festlegen des HTTP-Anforderungsparameters als übergebenen Wert im Fall von EditableValueHolder-Komponenten oder Einreihen eines neuen ActionEvent im Fall von ActionSource Komponenten), Konvertieren, Validieren und Aktualisieren der Modellwerte (nur EditableValueHolder Komponenten) und schließlich Aufrufen der in der Warteschlange befindlichen ActionEvent (nur ActionSource Komponenten). JSF überspringt die Verarbeitung aller anderen Komponenten, die nicht unter das Attribut process fallen. Außerdem werden Komponenten, deren Attribut rendered während der Phase zum Anwenden von Anforderungswerten zu false ausgewertet wird, als Teil des Schutzes vor manipulierten Anforderungen übersprungen.

Beachten Sie, dass es bei ActionSource-Komponenten (z. B. _<p:commandButton>_) sehr wichtig ist, dass Sie die Komponente selbst in das Attribut process aufnehmen, insbesondere, wenn Sie die mit der Komponente verknüpfte Aktion aufrufen möchten. Das folgende Beispiel, das nur bestimmte Eingabekomponenten verarbeiten soll, wenn eine bestimmte Befehlskomponente aufgerufen wird, funktioniert also nicht:

_<p:inputText id="foo" value="#{bean.foo}" />
<p:commandButton process="foo" action="#{bean.action}" />
_

Es würde nur den _#{bean.foo}_ und nicht den _#{bean.action}_ verarbeiten. Sie müssen auch die Befehlskomponente selbst einschließen:

_<p:inputText id="foo" value="#{bean.foo}" />
<p:commandButton process="@this foo" action="#{bean.action}" />
_

Oder, wie Sie anscheinend herausgefunden haben, mit _@parent_, wenn es sich zufällig um die einzigen Komponenten handelt, die ein gemeinsames übergeordnetes Element haben:

_<p:panel><!-- Type doesn't matter, as long as it's a common parent. -->
    <p:inputText id="foo" value="#{bean.foo}" />
    <p:commandButton process="@parent" action="#{bean.action}" />
</p:panel>
_

Oder wenn beide zufällig die einzigen Komponenten der übergeordneten UIForm Komponente sind, können Sie auch _@form_ verwenden:

_<h:form>
    <p:inputText id="foo" value="#{bean.foo}" />
    <p:commandButton process="@form" action="#{bean.action}" />
</h:form>
_

Dies ist manchmal unerwünscht, wenn das Formular mehr Eingabekomponenten enthält, die bei der Verarbeitung übersprungen werden sollen. Dies ist häufiger der Fall, wenn Sie andere Eingabekomponenten oder einen UI-Abschnitt basierend auf der aktuellen Eingabekomponente in aktualisieren möchten eine Ajax-Listener-Methode. Sie möchten nämlich nicht, dass Validierungsfehler bei anderen Eingabekomponenten die Ausführung der Ajax-Listener-Methode verhindern.

Dann ist da noch der _@all_. Dies hat keine besonderen Auswirkungen auf das Attribut process, sondern nur auf das Attribut update. Ein _process="@all"_ verhält sich genauso wie _process="@form"_. HTML unterstützt sowieso nicht das gleichzeitige Senden mehrerer Formulare.

Es gibt übrigens auch einen _@none_, der nützlich sein kann, wenn Sie absolut nichts verarbeiten müssen, aber nur bestimmte Teile über update aktualisieren möchten, insbesondere die Abschnitte, deren Inhalt nicht von übermittelten Werten oder Aktionslistenern abhängt.

Es sollte beachtet werden, dass das Attribut process keinen Einfluss auf die Nutzdaten der HTTP-Anforderung (die Anzahl der Anforderungsparameter) hat. Dies bedeutet, dass das standardmäßige HTML-Verhalten beim Senden von "allem", was in der HTML-Darstellung des _<h:form>_ enthalten ist, nicht beeinflusst wird. Wenn Sie über ein großes Formular verfügen und die Nutzdaten für HTTP-Anforderungen auf die für die Verarbeitung unbedingt erforderlichen Daten reduzieren möchten, dh nur die Daten, die vom Attribut process abgedeckt werden, können Sie das Attribut partialSubmit in den PrimeFaces Ajax-Komponenten wie in _<p:commandXxx ... partialSubmit="true">_ festlegen. oder _<p:ajax ... partialSubmit="true">_. Alternativ können Sie auch <o:form> von OmniFaces 3.0+ verwenden, das standardmäßig dieses Verhalten aufweist.

Das Standard-JSF-Äquivalent zum PrimeFaces-spezifischen process ist execute von _<f:ajax execute>_. Es verhält sich genauso, mit der Ausnahme, dass es keine durch Kommas getrennten Zeichenfolgen unterstützt, während es PrimeFaces unterstützt (obwohl ich persönlich empfehle, nur die durch Leerzeichen getrennten Konventionen einzuhalten), und auch nicht das Schlüsselwort _@parent_. Es kann auch nützlich sein zu wissen, dass _<p:commandXxx process>_ standardmäßig _@form_ ist, während _<p:ajax process>_ und _<f:ajax execute>_ standardmäßig _@this_ sind. Schließlich ist es auch nützlich zu wissen, dass process die sogenannten "PrimeFaces Selectors" unterstützt, siehe auch Wie funktionieren PrimeFaces Selectors wie in update = "@ (. MyClass)"?


_<p:commandXxx update>_ _<p:ajax update>_ _<f:ajax render>_

Das Attribut update ist clientseitig und kann die HTML-Darstellung aller UIComponents beeinflussen. Das Attribut update teilt JavaScript (das für die Verarbeitung der Ajax-Anforderung/Antwort verantwortlich ist) mithilfe einer durch Leerzeichen getrennten Liste von Client-IDs mit, welche Teile in der HTML-DOM-Struktur als Antwort auf das übermittelte Formular aktualisiert werden müssen.

JSF erstellt daraufhin die richtige Ajax-Antwort, die nur die zu aktualisierenden Teile enthält . JSF überspringt alle anderen Komponenten, die nicht durch das Attribut update in der Ajax-Antwort abgedeckt sind, wodurch die Antwortnutzlast gering gehalten wird. Außerdem werden Komponenten, deren Attribut rendered während der Render-Antwortphase zu false ausgewertet wird, übersprungen. Beachten Sie, dass JavaScript den Wert in der HTML-DOM-Struktur nicht aktualisieren kann, obwohl er true zurückgeben würde, wenn er ursprünglich false war. Sie müssten es umbrechen oder stattdessen das übergeordnete Element aktualisieren. Siehe auch Ajax Update/Render funktioniert nicht für eine Komponente, die das Attribut gerendert hat.

Normalerweise möchten Sie nur die Komponenten aktualisieren, die wirklich auf der Clientseite (teilweise) "aktualisiert" werden müssen ) Formular abschicken. Das folgende Beispiel aktualisiert das gesamte übergeordnete Formular über _@form_:

_<h:form>
    <p:inputText id="foo" value="#{bean.foo}" required="true" />
    <p:message id="foo_m" for="foo" />
    <p:inputText id="bar" value="#{bean.bar}" required="true" />
    <p:message id="bar_m" for="bar" />
    <p:commandButton action="#{bean.action}" update="@form" />
</h:form>
_

(Beachten Sie, dass das Attribut process weggelassen wird, da es standardmäßig _@form_ ist.)

Während dies gut funktionieren kann, ist die Aktualisierung von Eingabe- und Befehlskomponenten in diesem speziellen Beispiel nicht erforderlich. Wenn Sie die Modellwerte foo und bar nicht innerhalb der action -Methode ändern (was wiederum in der UX-Perspektive nicht intuitiv wäre), müssen Sie sie nicht aktualisieren. Die Nachrichtenkomponenten sind die einzigen, die wirklich aktualisiert werden müssen:

_<h:form>
    <p:inputText id="foo" value="#{bean.foo}" required="true" />
    <p:message id="foo_m" for="foo" />
    <p:inputText id="bar" value="#{bean.bar}" required="true" />
    <p:message id="bar_m" for="bar" />
    <p:commandButton action="#{bean.action}" update="foo_m bar_m" />
</h:form>
_

Das wird jedoch langweilig, wenn Sie viele von ihnen haben. Dies ist einer der Gründe, warum PrimeFaces Selectors existieren. Diese Nachrichtenkomponenten haben in der generierten HTML-Ausgabe die gemeinsame Stilklasse _ui-message_, daher sollte auch Folgendes gelten:

_<h:form>
    <p:inputText id="foo" value="#{bean.foo}" required="true" />
    <p:message id="foo_m" for="foo" />
    <p:inputText id="bar" value="#{bean.bar}" required="true" />
    <p:message id="bar_m" for="bar" />
    <p:commandButton action="#{bean.action}" update="@(.ui-message)" />
</h:form>
_

(Beachten Sie, dass Sie die IDs für Nachrichtenkomponenten beibehalten sollten, da andernfalls @(...) nicht funktioniert! Siehe auch Wie PrimeFaces-Selektoren wie in update = "@ (. myClass)" funktionieren ? für Details)

Der _@parent_ aktualisiert nur die übergeordnete Komponente, die somit die aktuelle Komponente und alle Geschwister und ihre Kinder abdeckt. Dies ist nützlicher, wenn Sie das Formular in vernünftige Gruppen mit jeweils eigener Verantwortung aufgeteilt haben. Der _@this_ aktualisiert offensichtlich nur die aktuelle Komponente. Normalerweise ist dies nur erforderlich, wenn Sie eines der HTML-Attribute der Komponente in der Aktionsmethode ändern müssen. Z.B.

_<p:commandButton action="#{bean.action}" update="@this" 
    oncomplete="doSomething('#{bean.value}')" />
_

Stellen Sie sich vor, das oncomplete muss mit dem in value geänderten action zusammenarbeiten. Dieses Konstrukt hätte dann nicht funktioniert, wenn die Komponente nicht aktualisiert worden wäre, da oncomplete Teil der generierten HTML-Ausgabe (und damit aller EL-Ausdrücke) ist in dort werden während des Renderns ausgewertet).

Der _@all_ aktualisiert das gesamte Dokument, das mit Sorgfalt verwendet werden sollte. Normalerweise möchten Sie stattdessen eine echte GET-Anforderung durch einen einfachen Link (_<a>_ oder _<h:link>_) oder eine Weiterleitung nach dem POST durch _?faces-redirect=true_ oder ExternalContext#redirect() verwenden. In Effekten hat _process="@form" update="@all"_ genau den gleichen Effekt wie eine nicht-ajax (nicht-partielle) Einreichung. In meiner gesamten JSF-Karriere ist der einzige sinnvolle Anwendungsfall, auf den ich bei _@all_ gestoßen bin, die vollständige Anzeige einer Fehlerseite, falls während einer Ajax-Anforderung eine Ausnahme auftritt. Siehe auch Wie gehe ich mit JSF 2.0-Ausnahmen für AJAXified-Komponenten richtig um?

Das Standard-JSF-Äquivalent zum PrimeFaces-spezifischen update ist render von _<f:ajax render>_. Es verhält sich genauso, mit der Ausnahme, dass es keine durch Kommas getrennten Zeichenfolgen unterstützt, während es PrimeFaces unterstützt (obwohl ich persönlich empfehle, nur die durch Leerzeichen getrennten Konventionen einzuhalten), und auch nicht das Schlüsselwort _@parent_. Sowohl update als auch render sind standardmäßig _@none_ (dh "nichts").


Siehe auch:

277
BalusC

Wenn Sie sich nur schwer an die Standardwerte erinnern können (ich weiß, ich habe ...), finden Sie hier einen kurzen Auszug aus der Antwort von BalusC:

 Komponente | Senden | Aktualisieren 
 ------------ | --------------- | -------------- 
 f: ajax | execute = "@ this" | render = "@ none" 
 p: ajax | process = "@ this" | update = "@ none" 
 p: commandXXX | process = "@ form" | update = "@ none" 
51
Jaqen H'ghar

Durch den Prozess (in der JSF-Spezifikation heißt er "Ausführen") weisen Sie JSF an, die Verarbeitung auf die angegebenen Komponenten zu beschränken. Alles andere wird einfach ignoriert.

update gibt an, welches Element aktualisiert wird, wenn der Server auf Ihre Anfrage antwortet.

@ all : Jede Komponente wird verarbeitet/gerendert.

@ this : Die anfordernde Komponente mit dem Ausführungsattribut wird verarbeitet/gerendert.

@ form : Das Formular, das die anfordernde Komponente enthält, wird verarbeitet/gerendert.

@ parent : Das übergeordnete Element, das die anfordernde Komponente enthält, wird verarbeitet/gerendert.

Mit Primefaces können Sie sogar JQuery-Selektoren verwenden. Sehen Sie sich dieses Blog an: http://blog.primefaces.org/?p=1867

23
faissalb