Comprender el proceso/actualización de PrimeFaces y los atributos de ejecución/renderización JSF f:ajax

Resuelto Shardendu asked hace 10 años • 5 respuestas

¿Qué son exactamente los componentes y processen updatePrimeFaces y en la etiqueta?p:commandXxxexecuterenderf:ajax

¿Cuál funciona al momento de la validación? ¿ Qué hace updateel atributo en lugar de actualizar el valor al componente desde el back-end? ¿El processatributo vincula el valor al modelo? ¿ Qué hacen exactamente @this, @parenty en ambos atributos?@all@form

El siguiente ejemplo funciona bien, pero estoy un poco confundido con los conceptos básicos.

<p:commandButton process="@parent"
                 update="@form"
                 action="#{bean.submit}" 
                 value="Submit" />
Shardendu avatar Aug 16 '14 17:08 Shardendu
Aceptado

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

El processatributo es del lado del servidor y solo puede afectar UIComponentla implementación EditableValueHolder(campos de entrada) o ActionSource(campos de comando). El processatributo le dice a JSF, utilizando una lista de ID de cliente separados por espacios, qué componentes deben procesarse exactamente durante todo el ciclo de vida de JSF al enviar el formulario (parcial).

Luego, JSF aplicará los valores de la solicitud (buscando el parámetro de solicitud HTTP basado en el ID de cliente del propio componente y luego configurándolo como valor enviado en el caso de EditableValueHoldercomponentes o poniendo en cola uno nuevo ActionEventen el caso de ActionSourcecomponentes), realizará la conversión, validación y actualización de los valores del modelo ( EditableValueHoldercomponentes solamente) y finalmente invocar los componentes en cola ActionEvent( ActionSourcesolo). JSF omitirá el procesamiento de todos los demás componentes que no estén cubiertos por processel atributo. Además, los componentes cuyo renderedatributo se evalúa falsedurante la fase de aplicación de valores de solicitud también se omitirán como parte de la protección contra solicitudes manipuladas.

ActionSourceTenga en cuenta que en el caso de componentes (como ) es <p:commandButton>muy importante que también incluya el componente en sí en el processatributo, especialmente si tiene la intención de invocar la acción asociada con el componente. Entonces, el siguiente ejemplo que pretende procesar solo ciertos componentes de entrada cuando se invoca un determinado componente de comando no 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ías incluir el componente de comando en sí:

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

O, como aparentemente descubrió, usar @parentsi son 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 son los únicos componentes del UIFormcomponente principal, también puede usar @form:

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

A veces, esto no es deseable si el formulario contiene más componentes de entrada que le gustaría omitir en el procesamiento, más a menudo en los casos en los 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 la ejecución del método de escucha ajax.

Luego está el @all. Esto no tiene ningún efecto especial en processel atributo, sino sólo en updateel atributo. A process="@all"se comporta exactamente igual que process="@form". De todos modos, HTML no admite el envío de varios formularios a la vez.

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

Cabe señalar que el atributo noprocess tiene influencia en la carga útil de la solicitud HTTP (la cantidad de parámetros de la solicitud). Es decir, el comportamiento HTML predeterminado de enviar "todo" lo contenido en la representación HTML de no se verá afectado. En caso de que tenga un formulario grande y desee reducir la carga útil de la solicitud HTTP solo a aquellos absolutamente necesarios en el procesamiento, es decir, solo aquellos cubiertos por atributo, puede configurar el atributo en los componentes PrimeFaces Ajax como en o . También puedes configurar esto 'globalmente' editando y agregando<h:form>processpartialSubmit<p:commandXxx ... partialSubmit="true"><p:ajax ... partialSubmit="true">web.xml

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

Alternativamente, también puede utilizar <o:form>OmniFaces 3.0+, que tiene este comportamiento de forma predeterminada.

El JSF estándar equivalente al específico de PrimeFaces processes executede <f:ajax execute>. Se comporta exactamente igual, excepto que no admite una cadena separada por comas, mientras que PrimeFaces sí lo hace (aunque personalmente recomiendo seguir la convención separada por espacios), ni la @parentpalabra clave. Además, puede resultar útil saber que <p:commandXxx process>el valor predeterminado es @formwhile <p:ajax process>y <f:ajax execute>el valor predeterminado @this. Finalmente, también es útil saber que processadmite los llamados "Selectores PrimeFaces". Consulte también ¿Cómo funcionan los selectores PrimeFaces como en update="@(.myClass)"?


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

El updateatributo es del lado del cliente y puede afectar la representación HTML de todos UIComponentlos mensajes. El updateatributo le dice a JavaScript (el responsable de manejar la solicitud/respuesta ajax), utilizando una lista de ID de cliente separados por espacios, qué partes del árbol HTML DOM deben actualizarse como respuesta al envío del formulario.

Luego, JSF preparará la respuesta ajax correcta para eso, que contendrá solo las partes solicitadas para actualizar. JSF omitirá todos los demás componentes que no estén cubiertos por el updateatributo en la respuesta ajax, manteniendo así pequeña la carga útil de la respuesta. Además, se omitirán los componentes cuyo renderedatributo se evalúe durante la fase de respuesta de renderizado. falseTenga en cuenta que, aunque regresaría true, JavaScript no puede actualizarlo en el árbol HTML DOM si lo estaba inicialmente false. En su lugar, necesitaría ajustarlo o actualizar su padre. Consulte también La actualización/renderizado de Ajax no funciona en un componente que tiene un atributo renderizado .

Por lo general, le gustaría actualizar sólo los componentes que realmente necesitan "actualizarse" en el lado del cliente al enviar el formulario (parcial). El siguiente ejemplo actualiza todo el formulario principal 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 processel atributo se omite porque @formya está predeterminado)

Si bien eso puede funcionar bien, la actualización de los componentes de entrada y comando es innecesaria en este ejemplo particular. A menos que cambie los valores del modelo fooy el método barinterno action(lo que a su vez no sería 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 resulta tedioso cuando tienes muchos de ellos. Esa es una de las razones por las que existen los selectores PrimeFaces. Esos componentes del mensaje tienen en la salida HTML generada una clase de estilo común de ui-message, por lo que también debería funcionar lo siguiente:

<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 conservar los ID de los componentes del mensaje; de ​​lo contrario, @(...)no funcionará. Nuevamente, consulte ¿Cómo funcionan los selectores PrimeFaces como en update="@(.myClass)"? para obtener más detalles)

Actualiza @parentsolo el componente principal, que por lo tanto cubre el componente actual y todos los hermanos y sus hijos. Esto es más útil si ha separado el formulario en grupos sensatos, cada uno con su propia responsabilidad. Las @thisactualizaciones, obviamente, sólo el componente actual. Normalmente, esto sólo es necesario cuando necesita cambiar uno de los atributos HTML propios del componente en el método de acción. P.ej

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

Imagine que oncompletenecesita trabajar con el valuecual se cambió en action, entonces esta construcción no habría funcionado si el componente no se actualiza, por la sencilla razón de que oncompletees parte de la salida HTML generada (y por lo tanto, todas las expresiones EL allí se evalúan durante la respuesta de renderizado).

Actualiza @alltodo el documento, que debe usarse con cuidado. Normalmente, le gustaría utilizar una solicitud GET verdadera para esto mediante un enlace simple ( <a>o <h:link>) o una redirección después de POST mediante ?faces-redirect=trueo ExternalContext#redirect(). En efecto, process="@form" update="@all"tiene exactamente el mismo efecto que un envío que no sea ajax (no parcial). En toda mi carrera en JSF, el único caso de uso sensato que encontré @allfue mostrar una página de error en su totalidad en caso de que ocurra una excepción durante una solicitud ajax. Consulte también ¿Cuál es la forma correcta de abordar las excepciones JSF 2.0 para componentes AJAXificados?

El JSF estándar equivalente al específico de PrimeFaces updatees renderde <f:ajax render>. Se comporta exactamente igual, excepto que no admite una cadena separada por comas, mientras que PrimeFaces sí lo hace (aunque personalmente recomiendo seguir la convención separada por espacios), ni la @parentpalabra clave. Ambos updatey renderpor defecto @none(que es "nada").


Ver también:

  • ¿Cómo averiguar el ID de cliente del componente para la actualización/renderizado de ajax? No se puede encontrar el componente con la expresión "foo" a la que se hace referencia desde "barra"
  • Orden de ejecución de eventos al presionar PrimeFaces p:commandButton
  • Cómo disminuir la carga útil de la solicitud de p:ajax durante, por ejemplo, la paginación de p:dataTable
  • Cómo mostrar los detalles de la fila actual de p:dataTable en ap:dialog y actualizar después de guardar
  • ¿Cómo utilizar <h:form> en la página JSF? ¿Forma única? ¿Múltiples formas? ¿Formularios anidados?
BalusC avatar Aug 17 '2014 07:08 BalusC

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

Componente Entregar Actualizar
f:ajax ejecutar="@esto" render="@ninguno"
p:ajax proceso="@esto" actualizar="@ninguno"
p:comandoXXX proceso="@formulario" actualizar="@ninguno"
Jaqen H'ghar avatar Aug 17 '2014 13:08 Jaqen H'ghar