web-dev-qa-db-fra.com

Quand utiliser valueChangeListener ou f: ajax listener?

Quelle est la différence entre les deux morceaux de code suivants - en ce qui concerne listener placement?

<h:selectOneMenu ...>
    <f:selectItems ... />
    <f:ajax listener="#{bean.listener}" />
</h:selectOneMenu>

et

<h:selectOneMenu ... valueChangeListener="#{bean.listener}">
    <f:selectItems ... />
</h:selectOneMenu>
83
Danijel

Le valueChangeListener ne sera invoqué que lorsque le formulaire sera soumis et la valeur soumise est différente de la valeur initiale. Il n'est donc pas appelé lorsque uniquement l'événement HTML DOM change est déclenché. Si vous souhaitez soumettre le formulaire lors de l'événement HTML DOM change, vous devez ajouter un autre <f:ajax/> Sans écouteur (!) Au composant d'entrée. Cela entraînera l'envoi d'un 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>

Lorsque vous utilisez <f:ajax listener> Au lieu de valueChangeListener, il est déjà exécuté par défaut lors de l'événement HTML DOM change. À l'intérieur des composants UICommand et des composants d'entrée représentant une case à cocher ou un radiobutton, il serait exécuté par défaut uniquement lors de l'événement HTML DOM click.

<h:selectOneMenu value="#{bean.value}">
    <f:selectItems ... />
    <f:ajax listener="#{bean.ajaxListener}" />
</h:selectOneMenu>

Une autre différence majeure est que la méthode valueChangeListener est invoquée à la fin de la phase PROCESS_VALIDATIONS. A ce moment, la valeur soumise n'est pas encore mise à jour dans le modèle. Vous ne pouvez donc pas l'obtenir simplement en accédant à la propriété de bean liée au composant value du composant d'entrée. Vous devez l'obtenir par ValueChangeEvent#getNewValue(). L'ancienne valeur est d'ailleurs également disponible avec ValueChangeEvent#getOldValue().

public void changeListener(ValueChangeEvent event) {
    Object oldValue = event.getOldValue();
    Object newValue = event.getNewValue();
    // ...
}

La méthode <f:ajax listener> Est invoquée pendant la phase INVOKE_APPLICATION. A 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é de bean liée au composant d'entrée value.

private Object value; // +getter+setter.

public void ajaxListener(AjaxBehaviorEvent event) {
    System.out.println(value); // Look, (new) value is already set.
}

De même, si vous devez mettre à jour une autre propriété en fonction de la valeur soumise, elle échouera si vous utilisez valueChangeListener comme la propriété mise à jour peut être remplacée par la valeur soumise au cours de la phase UPDATE_MODEL_VALUES suivante. C’est exactement pourquoi vous voyez dans les anciennes applications/tutoriels/ressources JSF 1.x qu’un valueChangeListener de cette construction a été utilisé en combinaison avec immediate="true" Et FacesContext#renderResponse() pour empêcher cela de passe. Après tout, utiliser le valueChangeListener pour exécuter des actions commerciales a toujours été une solution de contournement.

Résumé: utilisez le valueChangeListener uniquement si vous devez intercepter le changement de valeur réel. C'est à dire. vous êtes réellement intéressé par à la fois l’ancienne et la nouvelle valeur (par exemple, pour les consigner).

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 nouvelle valeur modifiée. C'est à dire. vous êtes réellement intéressé par seulement la nouvelle valeur (par exemple, pour remplir un deuxième menu déroulant).

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, retournez à valueChangeListener, mais mettez-la en file d'attente à la phase 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
    // ...
}
177
BalusC

pour le premier fragment (attribut auditeur ajax):

L'attribut "listener" d'une balise ajax est une méthode appelée côté serveur chaque fois que la fonction ajax est exécutée côté client. Par exemple, vous pouvez utiliser cet attribut pour spécifier une fonction côté serveur à appeler chaque fois que l'utilisateur appuie sur une touche.

mais le deuxième fragment (valueChangeListener):

ValueChangeListener ne sera appelé que lorsque le formulaire est soumis, et non lorsque la valeur de l'entrée est modifiée

* vous voudrez peut-être voir ceci réponse pratique

9
a.u.r