ajax - example - valuechangelistener picklist primefaces
¿Cuándo usar valueChangeListener o f: ajax listener? (2)
¿Cuál es la diferencia entre los siguientes dos códigos: con respecto a la ubicación del listener
?
<h:selectOneMenu ...>
<f:selectItems ... />
<f:ajax listener="#{bean.listener}" />
</h:selectOneMenu>
y
<h:selectOneMenu ... valueChangeListener="#{bean.listener}">
<f:selectItems ... />
</h:selectOneMenu>
para el primer fragmento (atributo de oyente ajax):
El atributo "oyente" de una etiqueta ajax es un método que se llama en el lado del servidor cada vez que la función ajax ocurre en el lado del cliente. Por ejemplo, puede usar este atributo para especificar una función del lado del servidor para llamar cada vez que el usuario presiona una tecla
pero el segundo fragmento (valueChangeListener):
El ValueChangeListener solo se invocará cuando se envíe el formulario, no cuando se cambie el valor de la entrada
* es posible que desee ver esta útil respuesta
valueChangeListener
solo se invocará cuando se valueChangeListener
el formulario y el valor enviado sea diferente del valor inicial. Por lo tanto, no se invoca cuando solo se activa el evento de change
HTML DOM. Si desea enviar el formulario durante el evento de change
HTML DOM, entonces deberá agregar otro <f:ajax/>
sin un oyente (!) Al componente de entrada. Causará un envío de formulario que procesa solo el componente actual (como en execute="@this"
).
<h:selectOneMenu value="#{bean.value}" valueChangeListener="#{bean.changeListener}">
<f:selectItems ... />
<f:ajax />
</h:selectOneMenu>
Cuando se usa <f:ajax listener>
lugar de valueChangeListener
, se ejecutaría de manera predeterminada durante el evento HTML DOM change
event. Dentro de los componentes de UICommand
y los componentes de entrada que representan una casilla de verificación o un UICommand
, se ejecutarán por defecto solo durante el evento de click
HTML DOM.
<h:selectOneMenu value="#{bean.value}">
<f:selectItems ... />
<f:ajax listener="#{bean.ajaxListener}" />
</h:selectOneMenu>
Otra diferencia importante es que el método valueChangeListener
se invoca al final de la fase PROCESS_VALIDATIONS
. En ese momento, el valor enviado aún no se ha actualizado en el modelo. Por lo tanto, no puede obtenerlo simplemente accediendo a la propiedad Bean que está vinculada al value
del componente de entrada. ValueChangeEvent#getNewValue()
obtenerlo por ValueChangeEvent#getNewValue()
. El valor anterior también está disponible por ValueChangeEvent#getOldValue()
.
public void changeListener(ValueChangeEvent event) {
Object oldValue = event.getOldValue();
Object newValue = event.getNewValue();
// ...
}
El método <f:ajax listener>
se invoca durante la fase INVOKE_APPLICATION
. En ese momento, el valor enviado ya se ha actualizado en el modelo. Puede obtenerlo accediendo directamente a la propiedad del bean que está vinculada al value
del componente de entrada.
private Object value; // +getter+setter.
public void ajaxListener(AjaxBehaviorEvent event) {
System.out.println(value); // Look, (new) value is already set.
}
Además, si necesita actualizar otra propiedad en función del valor enviado, fallaría cuando use valueChangeListener
ya que la propiedad actualizada puede anularse por el valor enviado durante la siguiente fase UPDATE_MODEL_VALUES
. Es exactamente por eso que se ve en aplicaciones / tutoriales / recursos antiguos de JSF 1.x que un valueChangeListener
está en tal construcción usado en combinación con immediate="true"
y FacesContext#renderResponse()
para evitar que eso ocurra. Después de todo, el uso de valueChangeListener
para ejecutar acciones comerciales en realidad siempre ha sido un truco / solución.
Resumido: utilice valueChangeListener
solo si necesita interceptar el cambio de valor real. Es decir, en realidad está interesado tanto en el valor antiguo como en el nuevo (por ejemplo, para registrarlos).
public void changeListener(ValueChangeEvent event) {
changeLogger.log(event.getOldValue(), event.getNewValue());
}
Use <f:ajax listener>
solo si necesita ejecutar una acción comercial sobre el valor recientemente cambiado. Es decir, en realidad solo está interesado en el nuevo valor (por ejemplo, para completar un segundo menú desplegable).
public void ajaxListener(AjaxBehaviorEvent event) {
selectItemsOfSecondDropdown = populateItBasedOn(selectedValueOfFirstDropdown);
}
Si también está interesado en el valor anterior mientras ejecuta una acción comercial, vuelva a valueChangeListener
, pero INVOKE_APPLICATION
fase INVOKE_APPLICATION
.
public void changeListener(ValueChangeEvent event) {
if (event.getPhaseId() != PhaseId.INVOKE_APPLICATION) {
event.setPhaseId(PhaseId.INVOKE_APPLICATION);
event.queue();
return;
}
Object oldValue = event.getOldValue();
Object newValue = event.getNewValue();
System.out.println(newValue.equals(value)); // true
// ...
}