Kiedy używać valueChangeListener lub F: ajax listener?

Jaka jest różnica pomiędzy dwoma poniższymi fragmentami kodu - jeśli chodzi o umieszczenie listener?

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

I

<h:selectOneMenu ... valueChangeListener="#{bean.listener}">
    <f:selectItems ... />
</h:selectOneMenu>
Author: BalusC, 2012-08-09

2 answers

Wartość valueChangeListener zostanie wywołana tylko wtedy, gdy formularz zostanie przesłany i podana wartość różni się od wartości początkowej. Nie jest więc wywoływany, gdy zostanie wywołane tylko Zdarzenie HTML DOM change. Jeśli chcesz przesłać formularz podczas zdarzenia HTML DOM change, musisz dodać kolejny <f:ajax/> bez listenera (!) do komponentu wejściowego. Spowoduje to wysłanie formularza, który przetwarza tylko bieżący komponent(jak w execute="@this").

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

Podczas stosowania <f:ajax listener> zamiast valueChangeListener, domyślnie wykonywałoby się to już podczas zdarzenia HTML DOM change. Wewnątrz komponentów UICommand i komponentów wejściowych reprezentujących pole wyboru lub radiobutton, domyślnie będzie ono wykonywane tylko podczas zdarzenia HTML DOM click.

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

Kolejną istotną różnicą jest to, że metoda valueChangeListener jest wywoływana na końcu fazy PROCESS_VALIDATIONS. W tym momencie podana wartość nie jest jeszcze aktualizowana w modelu. Więc nie można go uzyskać, po prostu dostęp do fasoli właściwość, która jest związana z elementem wejściowym value. Musisz ją zdobyć do ValueChangeEvent#getNewValue(). Stara wartość jest przy okazji dostępna również przez ValueChangeEvent#getOldValue().

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

Metoda <f:ajax listener> jest wywoływana w fazie INVOKE_APPLICATION. W tym momencie podana wartość jest już aktualizowana w modelu. Można go po prostu uzyskać poprzez bezpośredni dostęp do właściwości bean, która jest powiązana z komponentem wejściowym value.

private Object value; // +getter+setter.

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

Również, jeśli chcesz zaktualizować inną właściwość opartą na przekazana wartość nie powiedzie się, gdy używasz valueChangeListener, ponieważ zaktualizowana właściwość może zostać nadpisana przez przekazaną wartość podczas następnej fazyUPDATE_MODEL_VALUES. Właśnie dlatego widzisz w starym JSF 1.x aplikacje / samouczki / zasoby, które valueChangeListener znajduje się w takiej konstrukcji, zostały użyte w połączeniu z immediate="true" i FacesContext#renderResponse(), aby temu zapobiec. W końcu używanie valueChangeListener do wykonywania działań biznesowych zawsze było hack/obejściem.

Podsumowanie: użyj valueChangeListener tylko wtedy, gdy musisz przechwycić rzeczywistą zmianę wartości. Oznacza to, że jesteś zainteresowany zarówno starą, jak i nową wartością (np. aby je zalogować).

public void changeListener(ValueChangeEvent event) {
    changeLogger.log(event.getOldValue(), event.getNewValue());
}

Użyj <f:ajax listener> tylko wtedy, gdy musisz wykonać akcję biznesową na nowo zmienionej wartości. Oznacza to, że jesteś zainteresowany tylko nową wartością(np. aby wypełnić drugie rozwijane).

public void ajaxListener(AjaxBehaviorEvent event) {
    selectItemsOfSecondDropdown = populateItBasedOn(selectedValueOfFirstDropdown);
}

Jeśli faktycznie interesuje Cię również stara wartość podczas wykonywania akcji biznesowej, to powrót do valueChangeListener, ale kolejkowanie do fazy 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
    // ...
}
 163
Author: BalusC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-07 20:40:57

Dla pierwszego fragmentu (atrybut Ajax listener):

Atrybut "listener" znacznika ajax jest metodą, która jest wywoływana po stronie serwera za każdym razem, gdy funkcja ajax dzieje się po stronie klienta. Na przykład, można użyć tego atrybutu, aby określić funkcję po stronie serwera do wywołania za każdym razem, gdy użytkownik naciśnie klawisz

Ale drugi fragment (valueChangeListener):

Wartość zostanie wywołana tylko wtedy, gdy formularz zostanie złożony, a nie wtedy, gdy wartość input is changed

*you might like to view this handy answer

 9
Author: a.u.r,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:29