valueChangeListener
Zostanie 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 change
zdarzenia 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 change
zdarzenia HTML DOM . Wewnątrz UICommand
komponentów i komponentów wejściowych reprezentujących pole wyboru lub radiobutton byłby on domyślnie wykonywany tylko podczas click
zdarzenia HTML DOM .
<h:selectOneMenu value="#{bean.value}">
<f:selectItems ... />
<f:ajax listener="#{bean.ajaxListener}" />
</h:selectOneMenu>
Inną istotną różnicą jest to, że valueChangeListener
metoda jest wywoływana pod koniec PROCESS_VALIDATIONS
fazy. 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_APPLICATION
fazie. 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 valueChangeListener
zaktualizowanej właściwości, która może zostać zastąpiona przez przesłaną wartość w kolejnej UPDATE_MODEL_VALUES
fazie. Właśnie dlatego widzisz w starych aplikacjach / samouczkach / zasobach JSF 1.x, że element a valueChangeListener
jest 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 valueChangeListener
do wykonywania działań biznesowych zawsze było włamaniem / obejściem.
Podsumowanie: użyj valueChangeListener
tylko 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_APPLICATION
fazy.
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 ...