Comprensione processo / aggiornamento PrimeFaces e attributi JSF f: ajax eseguire / render


195

Cosa sono esattamente processe updatenei p:commandXxxcomponenti PrimeFaces executee rendernei f:ajaxtag?

Quale funziona al momento della convalida? Cosa fa l' updateattributo anziché aggiornare il valore al componente dal back-end? L' processattributo associa il valore al modello? Che cosa fare @this, @parent, @alle @formin entrambi gli attributi?

L'esempio che segue funziona bene, ma sono un po 'confuso nei concetti di base.

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

Risposte:


308

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

L' processattributo è lato server e può influire solo UIComponentsull'implementazione EditableValueHolder(campi di input) o ActionSource(campi di comando). L' processattributo indica a JSF, utilizzando un elenco separato da spazi di ID client, quali componenti devono essere elaborati esattamente durante l'intero ciclo di vita di JSF al momento dell'invio del modulo (parziale).

JSF applicherà quindi i valori della richiesta (trovando il parametro di richiesta HTTP basato sull'ID client del componente e quindi impostandolo come valore inviato in caso di EditableValueHoldercomponenti o accodando un nuovo ActionEventin caso di ActionSourcecomponenti), eseguirà la conversione, la convalida e l'aggiornamento dei valori del modello ( EditableValueHoldersolo componenti) e infine invocare l'accodamento ActionEvent( ActionSourcesolo componenti). JSF salterà l'elaborazione di tutti gli altri componenti che non sono coperti dall'attributo process. Inoltre, i componenti il ​​cui renderedattributo viene valutato falsedurante la fase di applicazione dei valori della richiesta verranno ignorati come parte della protezione contro le richieste manomesse.

Si noti che è nel caso di ActionSourcecomponenti (come <p:commandButton>) molto importanti che si includa anche il componente stesso processnell'attributo, in particolare se si intende invocare l'azione associata al componente. Quindi l'esempio seguente che intende elaborare solo determinati componenti di input quando viene invocato un determinato componente di comando non funzionerà:

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

Elaborerebbe solo il #{bean.foo}e non il #{bean.action}. Dovresti includere anche il componente del comando stesso:

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

Oppure, come apparentemente hai scoperto, usando @parentse capita di essere gli unici componenti con un genitore comune:

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

Oppure, se entrambi sono gli unici componenti del UIFormcomponente padre , puoi anche usare @form:

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

Questo a volte è indesiderabile se il modulo contiene più componenti di input che si desidera saltare durante l'elaborazione, più spesso nei casi in cui si desidera aggiornare un altro / i componente / i di input o una sezione dell'interfaccia utente in base al componente di input corrente in un metodo di ascolto ajax. In particolare, non vuoi che errori di convalida su altri componenti di input impediscano l'esecuzione del metodo listener ajax.

Poi c'è il @all. Questo non ha alcun effetto speciale in processattributo, ma solo in updateattributo. A si process="@all"comporta esattamente come process="@form". L'HTML non supporta comunque l'invio di più moduli contemporaneamente.

C'è anche un modo @noneche può essere utile nel caso in cui non sia assolutamente necessario elaborare nulla, ma si desidera aggiornare solo alcune parti specifiche tramite update, in particolare quelle sezioni il cui contenuto non dipende dai valori inviati o dai listener di azioni.

Si noti che l' processattributo non ha influenza sul payload della richiesta HTTP (la quantità di parametri della richiesta). Significato, il comportamento HTML predefinito di invio di "tutto" contenuto nella rappresentazione HTML del <h:form>non sarà influenzato. Nel caso in cui si disponga di un modulo di grandi dimensioni e si desideri ridurre il payload della richiesta HTTP a solo questi assolutamente necessari nell'elaborazione, ovvero solo quelli coperti da processattributo, è possibile impostare l' partialSubmitattributo nei componenti PrimeFaces Ajax come in <p:commandXxx ... partialSubmit="true">o <p:ajax ... partialSubmit="true">. Puoi anche configurarlo "a livello globale" modificando web.xmle aggiungendo

<context-param>
    <param-name>primefaces.SUBMIT</param-name>
    <param-value>partial</param-value>
</context-param>

In alternativa, è anche possibile utilizzare <o:form>OmniFaces 3.0+ per impostazione predefinita per questo comportamento.

Il JSF standard equivalente al primefaces specifica processè executeda <f:ajax execute>. Si comporta esattamente allo stesso modo tranne per il fatto che non supporta una stringa separata da virgola mentre quella di PrimeFaces (sebbene io personalmente raccomando di attenersi solo a una convenzione separata da spazi), né la @parentparola chiave. Inoltre, può essere utile sapere che l' <p:commandXxx process>impostazione predefinita è @formwhile <p:ajax process>e l' <f:ajax execute>impostazione predefinita è @this. Infine, è anche utile sapere che processsupporta i cosiddetti "selettori PrimeFaces", vedi anche Come funzionano i selettori PrimeFaces come in update = "@ (. MyClass)"?


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

L' updateattributo è lato client e può influire sulla rappresentazione HTML di tutti gli UIComponents. L' updateattributo indica a JavaScript (quello responsabile della gestione della richiesta / risposta ajax), utilizzando un elenco separato da spazi di ID client, quali parti dell'albero del DOM HTML devono essere aggiornate come risposta all'invio del modulo.

JSF preparerà quindi la risposta ajax giusta per quello, contenente solo le parti richieste da aggiornare. JSF salterà tutti gli altri componenti che non sono coperti dall'attributo updatenella risposta ajax, mantenendo così basso il carico utile della risposta. Inoltre, i componenti il ​​cui renderedattributo viene valutato falsedurante la fase di risposta al rendering verranno ignorati. Si noti che, sebbene restituisca true, JavaScript non può aggiornarlo nell'albero DOM HTML se inizialmente lo era false. Dovresti avvolgerlo o aggiornare invece il suo genitore. Vedi anche Ajax update / render non funziona su un componente che ha reso l'attributo .

Di solito, si desidera aggiornare solo i componenti che davvero hanno bisogno di essere "rinfrescato" nel lato client sul modulo (parziale) submit. L'esempio seguente aggiorna l'intero modulo padre tramite @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>

(nota che l' processattributo viene omesso in quanto predefinito per impostazione predefinita @form)

Sebbene ciò possa funzionare correttamente, l'aggiornamento di componenti di input e comandi in questo esempio particolare non è necessario. A meno che non modifichi i valori del modello fooe il metodo barinside action(che a sua volta non sarebbero intuitivi nella prospettiva UX), non ha senso aggiornarli. I componenti del messaggio sono gli unici che devono davvero essere aggiornati:

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

Tuttavia, diventa noioso quando ne hai molti. Questo è uno dei motivi per cui esistono i selettori PrimeFaces. Tali componenti del messaggio hanno nell'output HTML generato una classe di stile comune di ui-message, quindi anche le seguenti operazioni dovrebbero:

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

(nota che dovresti mantenere gli ID sui componenti del messaggio, altrimenti @(...)non funzionerà! Ancora una volta, vedi Come funzionano i selettori PrimeFaces come in update = "@ (. myClass)"? per i dettagli)

L' @parentaggiorna solo la componente principale, che copre così il componente corrente e tutti i fratelli ed i loro bambini. Questo è più utile se hai separato il modulo in gruppi sani con ognuno la propria responsabilità. Gli @thisaggiornamenti, ovviamente, solo il componente corrente. Normalmente, questo è necessario solo quando è necessario modificare uno degli attributi HTML del componente nel metodo di azione. Per esempio

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

Immagina che le oncompletenecessità di lavorare con le valuequali sono cambiate action, quindi questo costrutto non avrebbe funzionato se il componente non fosse aggiornato, per la semplice ragione che oncompletefa parte dell'output HTML generato (e quindi vengono valutate tutte le espressioni EL presenti durante la risposta di rendering).

Il @allaggiorna l'intero documento, che dovrebbe essere usato con cautela. Normalmente, si desidera utilizzare una vera richiesta GET per questo invece tramite un semplice link ( <a>o <h:link>) o un reindirizzamento-dopo-POST di ?faces-redirect=trueo ExternalContext#redirect(). In effetti, process="@form" update="@all"ha esattamente lo stesso effetto di un invio non ajax (non parziale). Durante la mia intera carriera in JSF, l'unico caso d'uso sensato che ho riscontrato @allè quello di visualizzare una pagina di errore nella sua interezza nel caso in cui si verifichi un'eccezione durante una richiesta Ajax. Vedi anche Qual è il modo corretto di gestire le eccezioni JSF 2.0 per i componenti AJAXified?

Il JSF standard equivalente al primefaces specifica updateè renderda <f:ajax render>. Si comporta esattamente allo stesso modo tranne per il fatto che non supporta una stringa separata da virgola mentre quella di PrimeFaces (sebbene io personalmente raccomando di attenersi solo a una convenzione separata dallo spazio), né alla @parentparola chiave. Entrambi updatee il rendervalore predefinito è @none(che è "niente").


Guarda anche:


Quando uso update = "", la proprietà gestita del backing bean non viene impostata e la mia routine @PostConstruct non riesce. qualche idea? MODIFICA: • Se si fa affidamento su una proprietà gestita di # {param} presente nelle successive richieste POST, è necessario includerla come <f: param> nei componenti UICommand.
K. Nicholas,

può un processo / aggiornamento di un panelGroup elaborerà / aggiornerà il contenuto di questo panelGroup ex: <h: panelGroup id = "pgId"> // i testi di input vanno qui <h: panelGroup> <p: commandLink process = "pgId" update = "pgId" />
bob-cac il

Grazie @BalusC per questa bellissima spiegazione!
ProgrammingIsAwsome

2
@Rapster: perché processnon è impostato, quindi utilizza il valore predefinito di @form. Questo è anche spiegato nella risposta sopra.
BalusC,

2
@Roland: sta nascondendo un problema diverso, più grave, con la configurazione dell'app.
BalusC

54

Se hai difficoltà a ricordare i valori predefiniti (so di avere ...) ecco un breve estratto della risposta di BalusC:

Componente | Invia | ricaricare
------------ | --------------- | --------------
f: ajax | execute = "@ this" | render = "@ none"
p: ajax | process = "@ this" | update = "@ none"
p: commandXXX | process = "@ form" | update = "@ none"

Solo una piccola correzione: il valore predefinito di processfor p:commandXXXè @all. Inoltre, questo sembra valere per ogni componente che supporta AJAX, come ad esempio p:menuitem.
Stephan Rauh,

1
Ciao @StephanRauh, grazie mille per il commento. Dove hai letto l'impostazione predefinita è @all? Per quanto posso leggere dalla risposta di BalusC, è @formcomunque @allequivalente a @formin corso. Buon punto sugli altri componenti, immagino che dovrò cercare nel codice sorgente quando sarà il momento di vedere a quali componenti si applica, poiché preferirei non scrivere qualcosa che potrebbe essere sbagliato
Jaqen H'ghar

1
@ JaqenH'ghar Thomas Andraschko mi ha raccontato qualcosa @all. Deve saperlo, ha recentemente implementato nuovamente il motore AJAX di PrimeFaces. Successivamente, ho ricontrollato ma leggendo il codice sorgente di PrimeFaces e guardando le richieste XHR. Spero di aver capito bene questa volta perché ho implementato le richieste AJAX di BootsFaces per funzionare in modo identico alle richieste AJAX di PrimeFaces.
Stephan Rauh,

Sarebbe fuorviante dire che il valore predefinito è @all quando HTML non supporta l'invio di più moduli. Gli sviluppatori devono conoscere il valore predefinito effettivo (quindi Thomas potrebbe modificarlo di conseguenza). A proposito, questi valori predefiniti sono erroneamente definiti null nella Guida dell'utente di Primefaces 6.2.
Marc Dzaebel,

27

Per processo (nella specifica JSF si chiama esegui) dici a JSF di limitare l'elaborazione al componente che viene specificato ogni altra cosa viene semplicemente ignorata.

update indica quale elemento verrà aggiornato quando il server risponderà alla tua richiesta.

@all : ogni componente viene elaborato / reso.

@questo : il componente richiedente con l'attributo di esecuzione viene elaborato / reso.

@form : il modulo che contiene il componente richiedente viene elaborato / reso.

@parent : il genitore che contiene il componente richiedente viene elaborato / reso.

Con Primefaces puoi persino utilizzare i selettori JQuery, consulta questo blog: http://blog.primefaces.org/?p=1867


2

Si noti che PrimeFaces supporta le parole chiave standard JSF 2.0+:

  • @this Componente attuale.
  • @all Vista intera.
  • @form Forma antenata più vicina del componente corrente.
  • @none Nessun componente

e le parole chiave standard JSF 2.3+:

  • @child(n) ennesimo figlio.
  • @composite Antenato componente composito più vicino.
  • @id(id) Utilizzato per cercare i componenti in base al loro ID ignorando la struttura ad albero dei componenti e denominando i contenitori.
  • @namingcontainer Contenitore di denominazione dell'antenato più vicino del componente corrente.
  • @parent Padre del componente corrente.
  • @previous Fratello precedente.
  • @next Il prossimo fratello.
  • @root L'istanza UIViewRoot della vista può essere utilizzata per avviare la ricerca dalla radice anziché dal componente corrente.

Ma include anche alcune parole chiave specifiche di PrimeFaces:

  • @row(n) ennesima riga.
  • @widgetVar(name) Componente con widget specificato Var.

E puoi anche usare qualcosa chiamato "Selettori PrimeFaces" che ti consente di usare l'API jQuery Selector. Ad esempio, per elaborare tutti gli input in un elemento con la classe CSS myClass:

process="@(.myClass :input)"

Vedere:


2
Nota che anche JSF2.3 + supporta la maggior parte delle parole chiave.
tandraschko,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.