web-dev-qa-db-fra.com

Compréhension des processus / mises à jour de PrimeFaces et des attributs d'exécution / de rendu f: ajax de JSF

Que sont exactement process et update dans les composants PrimeFaces p:commandXxx et execute et render dans f:ajax?

Qui fonctionne au moment de la validation? Que fait l'attribut update plutôt que de mettre à jour la valeur du composant depuis le serveur? Est-ce que l'attribut process lie la valeur au modèle? Que font exactement @this, @parent, @all et @form dans les deux attributs?

L'exemple ci-dessous fonctionne bien, mais je suis un peu confus dans les concepts de base.

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

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

L'attribut process est côté serveur et ne peut affecter que UIComponent s implémentant EditableValueHolder (champs de saisie) ou ActionSource (champs de commande). L'attribut process indique à JSF, à l'aide d'une liste d'ID de clients séparés par des espaces, quels composants doivent être traités exactement tout au long du cycle de vie de JSF lors de la soumission du formulaire (partiel).

JSF appliquera ensuite les valeurs de la demande (recherche du paramètre de la requête HTTP en fonction du propre ID client du composant, puis définition de la valeur soumise dans le cas des composants EditableValueHolder ou mise en file d'attente d'un nouveau ActionEvent dans le cas des composants ActionSource), effectuez la conversion, la validation et la mise à jour des valeurs de modèle (composants EditableValueHolder uniquement) et appelez enfin les éléments ActionEvent en file d'attente (composants ActionSource uniquement). JSF ignorera le traitement de tous les autres composants qui ne sont pas couverts par l'attribut process. De même, les composants dont l'attribut rendered est évalué à false au cours de la phase de définition des demandes d'application seront également ignorés dans le cadre de la protection contre les demandes altérées.

Notez que c'est très important dans le cas des composants ActionSource (tels que _<p:commandButton>_) d'inclure également le composant lui-même dans l'attribut process, en particulier si vous souhaitez invoquer l'action associée au composant. Ainsi, l'exemple ci-dessous qui vise à traiter uniquement certains composants d'entrée lorsqu'un composant de commande donné est appelé ne fonctionnera pas:

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

Il ne traiterait que le _#{bean.foo}_ et pas le _#{bean.action}_. Vous devez également inclure le composant de commande lui-même:

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

Ou, comme vous l'avez apparemment découvert, utilisez _@parent_ s'il s'agit des seuls composants ayant un parent commun:

_<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>
_

Ou, s’ils sont tous deux les seuls composants du composant parent UIForm , vous pouvez également utiliser _@form_:

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

Cela est parfois indésirable si le formulaire contient plusieurs composants d'entrée que vous souhaitez ignorer lors du traitement, plus souvent dans les cas où vous souhaitez mettre à jour un ou plusieurs composants d'entrée ou une section de l'interface utilisateur en fonction du composant d'entrée actuel. une méthode d'écoute ajax. Vous ne voulez surtout pas que les erreurs de validation sur d'autres composants d'entrée empêchent l'exécution de la méthode du programme d'écoute ajax.

Ensuite, il y a le _@all_. Cela n'a pas d'effet spécial dans l'attribut process, mais uniquement dans l'attribut update. Un _process="@all"_ se comporte exactement comme _process="@form"_. De toute façon, HTML ne permet pas de soumettre plusieurs formulaires à la fois.

Il existe également un _@none_ qui peut être utile au cas où vous n’auriez absolument pas besoin de traiter quoi que ce soit, mais seulement souhaitez mettre à jour certaines parties via update, en particulier les sections dont le contenu ne dépend pas des valeurs soumises ou des écouteurs d'action.

Il convient de noter que l'attribut process n'a aucune influence sur la charge utile de la demande HTTP (la quantité de paramètres de la demande). Cela signifie que le comportement HTML par défaut consistant à envoyer "tout" dans la représentation HTML de _<h:form>_ ne sera pas affecté. Si vous avez un formulaire volumineux et que vous souhaitez réduire la charge de requête HTTP à seulement celles qui sont absolument nécessaires au traitement, c’est-à-dire que celles-ci sont couvertes par l’attribut process, vous pouvez définir l’attribut partialSubmit dans les composants PrimeFaces Ajax comme dans _<p:commandXxx ... partialSubmit="true">_ ou _<p:ajax ... partialSubmit="true">_. Alternativement, vous pouvez également utiliser <o:form> d’OmniFaces 3.0+ qui adopte ce comportement par défaut.

L'équivalent JSF standard du process spécifique à PrimeFaces est execute à partir de _<f:ajax execute>_. Il se comporte exactement de la même manière, sauf qu'il ne prend pas en charge une chaîne séparée par des virgules, contrairement à PrimeFaces (bien que je recommande personnellement de s'en tenir à la convention séparant les espaces), ni le mot clé _@parent_. De même, il peut être utile de savoir que _<p:commandXxx process>_ par défaut est _@form_ while _<p:ajax process>_ et _<f:ajax execute>_ par défaut à _@this_. Enfin, il est également utile de savoir que process prend en charge les "sélecteurs PrimeFaces", voir aussi Comment fonctionnent les sélecteurs PrimeFaces dans update = "@ (. MyClass)"?


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

L'attribut update est côté client et peut affecter la représentation HTML de tous les UIComponents. L'attribut update indique à JavaScript (responsable de la gestion de la demande/réponse ajax), à l'aide d'une liste d'ID de clients séparés par des espaces, quelles parties de l'arborescence DOM HTML doivent être mises à jour en réponse à l'envoi du formulaire.

JSF préparera alors la bonne réponse ajax pour cela, contenant uniquement les parties à mettre à jour. JSF ignorera tous les autres composants qui ne sont pas couverts par l'attribut update dans la réponse ajax, gardant ainsi la charge utile de la réponse réduite. De même, les composants dont l'attribut rendered est évalué à false au cours de la phase de réponse au rendu seront ignorés. Notez que même s'il renvoie true, JavaScript ne peut pas le mettre à jour dans l'arborescence DOM HTML s'il était initialement false. Vous devez plutôt l’envelopper ou mettre à jour son parent. Voir aussi Ajax update/render ne fonctionne pas sur un composant qui a rendu l'attribut .

Généralement, vous souhaitez mettre à jour uniquement les composants qui réellement doivent être "actualisés" côté client ) formulaire soumettre. L'exemple ci-dessous met à jour le formulaire parent entier via _@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>
_

(notez que l'attribut process est omis car sa valeur par défaut est déjà _@form_)

Bien que cela puisse fonctionner correctement, la mise à jour des composants d’entrée et de commande est dans cet exemple particulier inutile. Si vous ne modifiez pas les valeurs de modèle foo et bar dans la méthode action (ce qui ne serait pas intuitif en perspective UX), il est inutile de les mettre à jour. Les composants du message sont les seuls qui doivent vraiment être mis à jour :

_<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>
_

Cependant, cela devient fastidieux lorsque vous en avez beaucoup. C'est l'une des raisons pour lesquelles PrimeFaces Selectors existe. Ces composants de message ont dans la sortie HTML générée une classe de style commun de _ui-message_. Par conséquent, les opérations suivantes doivent également être remplies:

_<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>
_

(notez que vous devez conserver les identifiants sur les composants du message, sinon @(...) ne fonctionnera pas! Encore une fois, voir Comment PrimeFaces Selectors fonctionne-t-il dans update = "@ (. myClass)"? pour plus de détails)

_@parent_ met à jour uniquement le composant parent, qui couvre donc le composant actuel, ainsi que tous les frères et soeurs et leurs enfants. Ceci est plus utile si vous avez séparé le formulaire en groupes sains avec chacun sa propre responsabilité. Le _@this_ met à jour, évidemment, uniquement le composant actuel. Normalement, cela n'est nécessaire que lorsque vous devez modifier l'un des attributs HTML du composant dans la méthode d'action. Par exemple.

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

Imaginez que oncomplete doive fonctionner avec value qui est modifié dans action, cette construction n’aurait pas fonctionné si le composant n’était pas mis à jour, pour la simple raison que oncomplete fait partie de la sortie HTML générée (et donc de toutes les expressions EL sont évalués lors de la réponse).

_@all_ met à jour tout le document, qui doit être utilisé avec précaution. Normalement, vous voudriez utiliser une vraie requête GET pour cela à la place soit par un lien simple (_<a>_ ou _<h:link>_), soit par une redirection après POST par _?faces-redirect=true_ ou ExternalContext#redirect(). Dans les effets, _process="@form" update="@all"_ a exactement le même effet qu'un envoi non ajax (non partiel). Dans toute ma carrière dans JSF, le seul cas d'utilisation raisonnable que j'ai rencontré pour _@all_ consiste à afficher une page d'erreur dans son intégralité au cas où une exception se produirait lors d'une requête ajax. Voir aussi Quelle est la bonne façon de traiter les exceptions JSF 2.0 pour les composants AJAXified?

L'équivalent JSF standard du update spécifique à PrimeFaces est render à partir de _<f:ajax render>_. Il se comporte exactement de la même manière, sauf qu'il ne prend pas en charge une chaîne séparée par des virgules, contrairement à PrimeFaces (bien que je recommande personnellement de s'en tenir à la convention séparant les espaces), ni le mot clé _@parent_. update et render ont tous les deux la valeur par défaut de _@none_ (qui est "rien").


Voir aussi:

277
BalusC

Si vous avez du mal à vous rappeler les valeurs par défaut (je sais que j'ai ...), voici un court extrait de la réponse de BalusC:

 Composant | Soumettre | Actualiser 
 ------------ | --------------- | -------------- 
 f: ajax | execute = "@ this" | render = "@ none" 
 p: ajax | process = "@ this" | update = "@ none" 
 p: commandXXX | process = "@ form" | update = "@ none" 
51
Jaqen H'ghar

Par processus (dans la spécification JSF, il est appelé exécuter), vous indiquez à JSF de limiter le traitement aux composants spécifiés. Tout le reste est simplement ignoré.

update indique quel élément sera mis à jour lorsque le serveur répondra à votre demande.

@ all : chaque composant est traité/rendu.

@ this : le composant demandeur avec l'attribut execute est traité/rendu.

@ form : le formulaire contenant le composant demandeur est traité/rendu.

@ parent : le parent qui contient le composant demandeur est traité/rendu.

Avec Primefaces, vous pouvez même utiliser les sélecteurs JQuery. Découvrez ce blog: http://blog.primefaces.org/?p=1867

23
faissalb