valueChangeListenerБуде викликано тільки тоді , коли форма була відправлена і представлене значення відрізняється від початкового значення. Таким чином, він не викликається, коли запускається лишеchange подія HTML DOM . Якщо ви хочете надіслати форму під час changeподії HTML DOM , вам потрібно буде додати іншу <f:ajax/>без прослуховувача (!) До вхідного компонента. Це призведе до подання форми, яка обробляє лише поточний компонент (як у execute="@this").
<h:selectOneMenu value="#{bean.value}" valueChangeListener="#{bean.changeListener}">
<f:selectItems ... />
<f:ajax />
</h:selectOneMenu>
При використанні <f:ajax listener>замість цього valueChangeListenerвін за замовчуванням виконується під час changeподії HTML DOM . Усередині UICommandкомпонентів та вхідних компонентів, що представляють прапорець або перемикач, воно за замовчуванням виконується лише під час clickподії HTML DOM .
<h:selectOneMenu value="#{bean.value}">
<f:selectItems ... />
<f:ajax listener="#{bean.ajaxListener}" />
</h:selectOneMenu>
Інша важлива відмінність полягає в тому, що valueChangeListenerметод викликається в кінці PROCESS_VALIDATIONSфази. На даний момент подане значення ще не оновлено в моделі. Отже, ви не можете отримати його, просто отримавши доступ до властивості bean, яка прив’язана до вхідного компонента value. Вам потрібно це здобути ValueChangeEvent#getNewValue(). Старе значення, до речі, також доступне і ValueChangeEvent#getOldValue().
public void changeListener(ValueChangeEvent event) {
Object oldValue = event.getOldValue();
Object newValue = event.getNewValue();
}
<f:ajax listener>Метод викликається під час INVOKE_APPLICATIONфази. На той момент подане значення вже оновлено у моделі. Ви можете просто отримати його, безпосередньо отримавши доступ до властивості bean, яка прив’язана до вхідного компонента value.
private Object value;
public void ajaxListener(AjaxBehaviorEvent event) {
System.out.println(value);
}
Крім того, якщо вам потрібно буде оновити інше властивість на основі поданого значення, воно не вдасться, коли ви використовуєте, valueChangeListenerоскільки оновлене властивість може бути замінено надісланим значенням на наступному UPDATE_MODEL_VALUESетапі. Саме тому ви бачите у старих програмах / навчальних посібниках / ресурсах JSF 1.x, що a valueChangeListenerу такій конструкції використовувалося в поєднанні з immediate="true"і FacesContext#renderResponse()для запобігання цьому. Зрештою, використання valueChangeListenerдля виконання бізнес-дій насправді завжди було хаком / обхідним шляхом.
Підсумовано: Використовуйте valueChangeListenerєдине, якщо вам потрібно перехопити фактичну зміну значення. Тобто вас насправді цікавлять як старі, так і нові значення (наприклад, щоб їх реєструвати).
public void changeListener(ValueChangeEvent event) {
changeLogger.log(event.getOldValue(), event.getNewValue());
}
Використовуйте <f:ajax listener>єдине, якщо вам потрібно виконати ділову дію щодо нещодавно зміненого значення. Тобто вас насправді цікавить лише нове значення (наприклад, заповнити другий випадаючий список).
public void ajaxListener(AjaxBehaviorEvent event) {
selectItemsOfSecondDropdown = populateItBasedOn(selectedValueOfFirstDropdown);
}
Якщо насправді вас також цікавить старе значення під час виконання ділової дії, поверніться до valueChangeListener, але поставте його в чергу до 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));
}
logger.trace( "setting changeTypes from {} to {}", this.changeTypes, changeTypes );. Здається, ви могли б використовувати старі та нові значення, отримані таким чином, для ведення ділової логіки безпосередньо в сетері, а також для простого ведення журналу, але я не знаю, чи це може спричинити побічні ефекти ...