Le valueChangeListener
ne sera invoqué que lorsque le formulaire est soumis et que la valeur soumise est différente de la valeur initiale. Il n'est donc pas appelé lorsque seul l' change
événement HTML DOM est déclenché. Si vous souhaitez soumettre le formulaire pendant l' change
événement HTML DOM , vous devez en ajouter un autre <f:ajax/>
sans écouteur (!) Au composant d'entrée. Cela entraînera une soumission de formulaire qui ne traite que le composant actuel (comme dans execute="@this"
).
<h:selectOneMenu value="#{bean.value}" valueChangeListener="#{bean.changeListener}">
<f:selectItems ... />
<f:ajax />
</h:selectOneMenu>
Lors de l'utilisation <f:ajax listener>
au lieu de valueChangeListener
, il serait déjà exécuté par défaut lors de l' change
événement HTML DOM . À l'intérieur des UICommand
composants et des composants d'entrée représentant une case à cocher ou un radiobutton, il serait par défaut exécuté pendant l' click
événement HTML DOM uniquement.
<h:selectOneMenu value="#{bean.value}">
<f:selectItems ... />
<f:ajax listener="#{bean.ajaxListener}" />
</h:selectOneMenu>
Une autre différence majeure est que la valueChangeListener
méthode est appelée à la fin de la PROCESS_VALIDATIONS
phase. À ce moment, la valeur soumise n'est pas encore mise à jour dans le modèle. Vous ne pouvez donc pas l'obtenir en accédant simplement à la propriété du bean qui est liée au composant d'entrée value
. Vous devez y arriver ValueChangeEvent#getNewValue()
. L'ancienne valeur est d'ailleurs également disponible par ValueChangeEvent#getOldValue()
.
public void changeListener(ValueChangeEvent event) {
Object oldValue = event.getOldValue();
Object newValue = event.getNewValue();
}
La <f:ajax listener>
méthode est appelée pendant la INVOKE_APPLICATION
phase. À ce moment, la valeur soumise est déjà mise à jour dans le modèle. Vous pouvez simplement l'obtenir en accédant directement à la propriété du bean qui est liée au composant d'entrée value
.
private Object value;
public void ajaxListener(AjaxBehaviorEvent event) {
System.out.println(value);
}
De plus, si vous devez mettre à jour une autre propriété en fonction de la valeur soumise, elle échouera lorsque vous l'utilisez, valueChangeListener
car la propriété mise à jour peut être remplacée par la valeur soumise lors de la UPDATE_MODEL_VALUES
phase suivante . C'est exactement pourquoi vous voyez dans les anciennes applications / tutoriels / ressources JSF 1.x qu'un valueChangeListener
est dans une telle construction a été utilisé en combinaison avec immediate="true"
et FacesContext#renderResponse()
pour empêcher que cela se produise. Après tout, l'utilisation de valueChangeListener
pour exécuter des actions commerciales a toujours été un hack / une solution de contournement.
Résumé: utilisez le valueChangeListener
uniquement si vous devez intercepter le changement de valeur réelle lui-même. -À- dire que vous êtes réellement intéressé à la fois l'ancienne et la nouvelle valeur (par exemple pour les log).
public void changeListener(ValueChangeEvent event) {
changeLogger.log(event.getOldValue(), event.getNewValue());
}
Utilisez le <f:ajax listener>
uniquement si vous devez exécuter une action commerciale sur la valeur nouvellement modifiée. C'est-à-dire que vous n'êtes réellement intéressé que par la nouvelle valeur (par exemple pour remplir une deuxième liste déroulante).
public void ajaxListener(AjaxBehaviorEvent event) {
selectItemsOfSecondDropdown = populateItBasedOn(selectedValueOfFirstDropdown);
}
Si vous êtes également intéressé par l'ancienne valeur lors de l'exécution d'une action commerciale, revenez valueChangeListener
à la INVOKE_APPLICATION
phase , mais mettez-la en file d'attente .
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));
}
logger.trace( "setting changeTypes from {} to {}", this.changeTypes, changeTypes );
. Il semble que vous puissiez utiliser les anciennes et les nouvelles valeurs obtenues de cette manière pour faire de la logique métier directement dans le setter ainsi qu'une simple journalisation, mais je ne sais pas si cela provoquerait des effets secondaires ...