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 );
. Здається, ви могли б використовувати старі та нові значення, отримані таким чином, для ведення ділової логіки безпосередньо в сетері, а також для простого ведення журналу, але я не знаю, чи це може спричинити побічні ефекти ...