Descripción de PrimeFaces process / update y JSF f: ajax execute/render attributes


¿Qué son exactamente process y update en los componentes PrimeFaces p:commandXxx y execute y render en la etiqueta f:ajax?

¿Qué funciona en el momento de la validación? ¿Qué hace el atributo update en lugar de actualizar el valor al componente desde el back-end? ¿process atribuye el valor de enlace al modelo? Qué hacer exactamente @this, @parent, @all y @form en ambos atributos?

El siguiente ejemplo está funcionando bien, pero estoy un poco confundido en conceptos básicos.

<p:commandButton process="@parent"
                 update="@form"
                 action="#{bean.submit}" 
                 value="Submit" />
Author: BalusC, 2014-08-16

3 answers

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

El atributo process es del lado del servidor y solo puede afectar UIComponents implementing EditableValueHolder (campos de entrada) o ActionSource (campos de comando). El atributo process le dice a JSF, usando una lista separada por espacios de ID de cliente, qué componentes deben procesarse exactamente a través de todo el ciclo de vida de JSF al enviar el formulario (parcial).

JSF luego aplicará los valores de la solicitud (encontrando el parámetro de solicitud HTTP basado en el componente ID de cliente propio y luego configurarlo como valor enviado en el caso de componentes EditableValueHolder o poner en cola un nuevoActionEvent en caso de componentes ActionSource), realice la conversión, validación y actualización de los valores del modelo (solo componentesEditableValueHolder) y finalmente invoque la cola ActionEvent (ActionSource componentes solamente). JSF omitirá el procesamiento de todos los demás componentes que no estén cubiertos por el atributo process. Además, los componentes cuyo atributo rendered evalúa a false durante la fase aplicar valores de solicitud también se omitirá como parte de la protección contra solicitudes manipuladas.

Tenga en cuenta que en el caso de componentes ActionSource (como <p:commandButton>) es muy importante que también incluya el propio componente en el atributo process, especialmente si tiene la intención de invocar la acción asociada con el componente. Así que el siguiente ejemplo que intenta procesar solo ciertos componentes de entrada cuando se invoca un determinado componente de comando no va a funcionar:

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

Solo procesaría el #{bean.foo} y no el #{bean.action}. También necesitarás incluir el componente de comando:

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

O, como aparentemente descubriste, usando @parent si resultan ser los únicos componentes que tienen un padre común:

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

O, si ambos resultan ser los únicos componentes del padre UIForm componente, entonces también puede usar @form:

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

Esto a veces es indeseable si el formulario contiene más componentes de entrada que desea omitir procesamiento, más que a menudo en los casos en que desea actualizar otro(s) componente (s) de entrada o alguna sección de la interfaz de usuario basada en el componente de entrada actual en un método de escucha ajax. Es decir, no desea que los errores de validación en otros componentes de entrada impidan que se ejecute el método de escucha ajax.

Luego está el @all. Esto no tiene ningún efecto especial en el atributo process, sino solo en el atributo update. A process="@all" se comporta exactamente igual que process="@form". HTML no es compatible enviar múltiples formularios a la vez de todos modos.

Por cierto, también hay un @none que puede ser útil en caso de que no necesite procesar nada, pero solo desea actualizar algunas partes específicas a través de update, particularmente aquellas secciones cuyo contenido no depende de los valores enviados o de los oyentes de acciones.

Se debe tener en cuenta que el atributo process tiene ninguna influencia en la carga útil de la solicitud HTTP (la cantidad de parámetros de la solicitud). Es decir, la el comportamiento HTML predeterminado de enviar "todo" contenido dentro de la representación HTML de <h:form> no se verá afectado. En caso de que tenga un formulario grande, y desee reducir la carga útil de la solicitud HTTP a solo los absolutamente necesarios en el procesamiento, es decir, solo los cubiertos por el atributo process, entonces puede establecer el atributo partialSubmit en los componentes Ajax de PrimeFaces como en <p:commandXxx ... partialSubmit="true"> o <p:ajax ... partialSubmit="true">. Alternativamente, también puede utilizar <o:form> de OmniFaces 3.0 + que por defecto es comportamiento.

El JSF estándar equivalente a las PrimeFaces específicas process es execute de <f:ajax execute>. Se comporta exactamente igual, excepto que no admite una cadena separada por comas mientras que las PrimeFaces sí (aunque personalmente recomiendo simplemente atenerse a la convención separada por espacios), ni la palabra clave @parent. Además, puede ser útil saber que <p:commandXxx process> por defecto es @form mientras que <p:ajax process> y <f:ajax execute> por defecto es @this. Finalmente, también es útil saber que process soporta los llamados "PrimeFaces Selectors", véase también Cómo funcionan los PrimeFaces Selectors como en update="@(.MyClass) " work?


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

El atributo update es del lado del cliente y puede afectar la representación HTML de todos los UIComponent s. El atributo update le dice a JavaScript (el responsable de manejar la solicitud/respuesta ajax), usando una lista separada por espacios de ID de cliente, qué partes del árbol DOM HTML deben actualizarse como respuesta al formulario submit.

JSF preparará la respuesta ajax correcta para eso, conteniendo solo las partes solicitadas para actualizar. JSF omitirá todos los demás componentes que no estén cubiertos por el atributo update en la respuesta ajax, manteniendo así la carga útil de la respuesta pequeña. Además, los componentes cuyo atributo rendered evalúa a false durante la fase de respuesta de renderizado se omitirán. Tenga en cuenta que a pesar de que devolvería true, JavaScript no puede actualizarlo en el árbol DOM HTML si fue inicialmente false. Tendría que envolverlo o actualizar su padre en su lugar. Véase también Ajax update/render no funciona en un componente que haya renderizado el atributo.

Por lo general, le gustaría actualizar solo los componentes que realmente necesitan ser "actualizados" en el lado del cliente al enviar el formulario (parcial). El siguiente ejemplo actualiza todo el formulario padre a través de @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>

(tenga en cuenta que el atributo process se omite ya que el valor predeterminado es @form ya)

Si bien esto puede funcionar bien, la actualización de los componentes de entrada y comando es innecesaria en este ejemplo en particular. A menos que cambie los valores del modelo foo y bar dentro del método action (que a su vez sería poco intuitivo en la perspectiva de UX), no tiene sentido actualizarlos. Los componentes del mensaje son los únicos que realmente necesitan ser actualizados:

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

Sin embargo, eso se vuelve tedioso cuando tienes muchos de ellos. Esa es una de las razones por las Existen selectores PrimeFaces. Esos componentes del mensaje tienen en la salida HTML generada una clase de estilo común de ui-message, por lo que lo siguiente también debería hacer:

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

(tenga en cuenta que debe mantener los IDs en los componentes del mensaje, de lo contrario @(...) no funcionará! De nuevo, vea Cómo funcionan los selectores PrimeFaces como en update="@(.MyClass) " work? para más detalles)

El @parent actualiza solo el componente padre, que por lo tanto cubre el componente actual y todos los hermanos y su niño. Esto es más útil si ha separado el formulario en grupos sanos con cada uno su propia responsabilidad. El @this actualiza, obviamente, solo el componente actual. Normalmente, esto solo es necesario cuando necesita cambiar uno de los atributos HTML propios del componente en el método action. Por ejemplo,

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

Imagine que el oncomplete necesita trabajar con el value que se cambia en action, entonces esta construcción no habría funcionado si el componente no se actualiza, por la simple razón de que oncomplete es parte de la salida HTML generada (y por lo tanto todas las expresiones EL allí son evaluadas durante la respuesta de render).

El @all actualiza todo el documento, que debe usarse con cuidado. Normalmente, te gustaría usar una solicitud GET verdadera para esto en lugar de un enlace simple (<a> o <h:link>) o un redireccionamiento posterior de ?faces-redirect=true o ExternalContext#redirect(). En effects, process="@form" update="@all" tiene exactamente el mismo efecto que un envío no ajax (no parcial). En toda mi carrera JSF, el único caso de uso sensato I encontrado para @all es mostrar una página de error en su totalidad en caso de que se produzca una excepción durante una solicitud ajax. Ver también ¿Cuál es la forma correcta de tratar con las excepciones JSF 2.0 para los componentes AJAXified?

El JSF estándar equivalente a las PrimeFaces específicas update es render de <f:ajax render>. Se comporta exactamente igual, excepto que no admite una cadena separada por comas mientras que la PrimeFaces lo hace (aunque personalmente recomiendo que solo se adhiera a convención separada por espacios), ni la palabra clave @parent. Tanto update como render tienen por defecto @none (que es, "nada").


Véase también:

 251
Author: BalusC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-25 14:24:20

Si tiene dificultades para recordar los valores predeterminados (sé que los tengo... he aquí un breve extracto de la respuesta de BalusC:

Component    | Submit          | Refresh
------------ | --------------- | --------------
f:ajax       | execute="@this" | render="@none"
p:ajax       | process="@this" | update="@none"
p:commandXXX | process="@form" | update="@none"
 47
Author: Jaqen H'ghar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-26 21:38:09

Por proceso (en la especificación JSF se llama execute) le dices a JSF que limite el procesamiento a los componentes que se especifican.

Update indica qué elemento se actualizará cuando el servidor responda a su solicitud.

@todos : Cada componente es procesado/renderizado.

@: El componente solicitante con el atributo execute es procesado/renderizado.

@forma : La forma que contiene la el componente que solicita es procesado / renderizado.

@parent : El padre que contiene el componente solicitante es procesado/renderizado.

Con Primefaces incluso puedes usar selectores jQuery, echa un vistazo a este blog: http://blog.primefaces.org/?p=1867

 21
Author: faissalb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-16 12:22:47