valueChangeListenerZostanie wywołany tylko wtedy, gdy formularz jest składany i przedłożone wartość różni się od wartości początkowej. Dlatego nie jest wywoływana, gdy uruchamiane jest tylkochange zdarzenie HTML DOM . Jeśli chcesz wysłać formularz podczas changezdarzenia HTML DOM , musisz dodać kolejny <f:ajax/>bez listenera (!) Do komponentu wejściowego. Spowoduje to przesł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>
W przypadku użycia <f:ajax listener>zamiast valueChangeListener, byłoby to domyślnie wykonywane już podczas changezdarzenia HTML DOM . Wewnątrz UICommandkomponentów i komponentów wejściowych reprezentujących pole wyboru lub radiobutton byłby on domyślnie wykonywany tylko podczas clickzdarzenia HTML DOM .
<h:selectOneMenu value="#{bean.value}">
<f:selectItems ... />
<f:ajax listener="#{bean.ajaxListener}" />
</h:selectOneMenu>
Inną istotną różnicą jest to, że valueChangeListenermetoda jest wywoływana pod koniec PROCESS_VALIDATIONSfazy. W tym momencie podana wartość nie jest jeszcze aktualizowana w modelu. Więc nie możesz tego uzyskać, po prostu uzyskując dostęp do właściwości bean, która jest powiązana z komponentem wejściowym value. Musisz to zrobić ValueChangeEvent#getNewValue(). Nawiasem mówiąc, stara wartość jest również dostępna przez ValueChangeEvent#getOldValue().
public void changeListener(ValueChangeEvent event) {
Object oldValue = event.getOldValue();
Object newValue = event.getNewValue();
}
<f:ajax listener>Sposób wywoływany jest w INVOKE_APPLICATIONfazie. W tym momencie przesłana wartość jest już zaktualizowana w modelu. Możesz go po prostu uzyskać, uzyskując bezpośredni dostęp do właściwości bean, która jest powiązana ze składnikiem wejściowym value.
private Object value;
public void ajaxListener(AjaxBehaviorEvent event) {
System.out.println(value);
}
Ponadto, jeśli musisz zaktualizować inną właściwość na podstawie przesłanej wartości, to zakończy się niepowodzeniem, gdy używasz valueChangeListenerzaktualizowanej właściwości, która może zostać zastąpiona przez przesłaną wartość w kolejnej UPDATE_MODEL_VALUESfazie. Właśnie dlatego widzisz w starych aplikacjach / samouczkach / zasobach JSF 1.x, że element a valueChangeListenerjest w takiej konstrukcji został użyty w połączeniu z immediate="true"i FacesContext#renderResponse()aby temu zapobiec. W końcu korzystanie z narzędzia valueChangeListenerdo wykonywania działań biznesowych zawsze było włamaniem / obejściem.
Podsumowanie: użyj valueChangeListenertylko wtedy, gdy musisz przechwycić samą zmianę wartości. Oznacza to, że jesteś zainteresowany zarówno starą, jak i nową wartością (np. Aby je zarejestrować).
public void changeListener(ValueChangeEvent event) {
changeLogger.log(event.getOldValue(), event.getNewValue());
}
Użyj <f:ajax listener>tylko, jeśli musisz wykonać akcję biznesową na nowo zmienionej wartości. Oznacza to, że interesuje Cię tylko nowa wartość (np. Aby wypełnić drugie menu).
public void ajaxListener(AjaxBehaviorEvent event) {
selectItemsOfSecondDropdown = populateItBasedOn(selectedValueOfFirstDropdown);
}
Jeśli faktycznie interesuje Cię stara wartość podczas wykonywania czynności biznesowej, wróć do valueChangeListener, ale ustaw ją w kolejce do INVOKE_APPLICATIONfazy.
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 );. Wygląda na to, że można by wykorzystać stare i nowe wartości uzyskane w ten sposób do wykonywania logiki biznesowej bezpośrednio w ustawiaczu, a także do prostego logowania, ale nie wiem, czy to spowodowałoby skutki uboczne ...