В этой статье я хотел бы остановиться на очень распространенном случае использования af: popup, содержащем af: диалог с входными компонентами внутри. Есть несколько подводных камней, на которые мы должны обратить внимание при реализации этого варианта использования.
Давайте рассмотрим простой пример:
|
1
2
3
4
5
6
7
8
|
<af:popup id="p1" contentDelivery="lazyUncached"> <af:dialog id="d2" title="Dialog" > <af:inputText value="#{TheBean.firstName}" label="First Name" id="it1"/> <af:inputText value="#{TheBean.lastName}" label="Last Name" id="it2"/> </af:dialog> </af:popup> |
Самым интересным здесь является свойство contentDelivery всплывающего окна, для которого установлено значение lazyUncached . Это предотвращает кэширование всплывающих входных значений и заставляет его получать значения из модели при каждом запросе вместо использования значений из кэша.
Давайте сделаем пример немного сложнее. В установщике lastName мы собираемся сгенерировать исключение:
|
1
2
3
4
|
public void setLastName(String lastName) throws Exception { this.lastName = lastName; throw new Exception("This last name is bad");} |
Итак, очевидно, что если мы попытаемся отправить диалог, мы получим следующее:

Входные значения не могут быть переданы в модель, и они будут сохранены в локальных значениях входных компонентов. Эти локальные значения не будут очищены, даже если мы нажмем кнопку « Отмена» , и эти значения будут использоваться во время запроса подпоследовательности. Чтобы предотвратить это, мы должны установить свойство resetEditableValues для всплывающего окна в whenCanceled . Как это:
|
1
2
3
4
5
6
7
8
9
|
<af:popup id="p1" contentDelivery="lazyUncached" resetEditableValues="whenCanceled"> <af:dialog id="d2" title="Dialog" > <af:inputText value="#{TheBean.firstName}" label="First Name" id="it1"/> <af:inputText value="#{TheBean.lastName}" label="Last Name" id="it2"/> </af:dialog> </af:popup> |
Давайте рассмотрим пример диалога af: с пользовательскими кнопками:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
<af:popup id="p1" contentDelivery="lazyUncached" resetEditableValues="whenCanceled" binding="#{TheBean.popup}"> <af:dialog id="d2" title="Dialog" type="none"> <af:inputText value="#{TheBean.firstName}" label="First Name" id="it1"/> <af:inputText value="#{TheBean.lastName}" label="Last Name" id="it2"/> <f:facet name="buttonBar"> <af:panelGroupLayout layout="horizontal" id="pgl1"> <af:button text="Ok" id="b2" actionListener="#{TheBean.buttonActionListener}"/> <af:button text="Cancel" id="b3" immediate="true" actionListener="#{TheBean.buttonActionListener}"/> </af:panelGroupLayout> </f:facet> </af:dialog> </af:popup> |
Итак, есть две пользовательские кнопки «Ok» и «Cancel» со следующим actionListener :
|
1
2
3
|
public void buttonActionListener(ActionEvent actionEvent) { getPopup().hide();} |
В этом случае resetEditableValues не работает, и локальные значения компонентов ввода не будут очищены при нажатии кнопки Отмена . Есть несколько вариантов решения этой проблемы.
Первый — добавить af: resetListener к кнопке Cancel:
|
1
2
3
4
|
<af:button text="Cancel" id="b3" immediate="true" actionListener="#{TheBean.buttonActionListener}"> <af:resetListener type="action"/> </af:button> |
Второй вариант — отменить всплывающее окно, а не просто скрыть его в слушателе действия кнопки «Отмена»:
|
1
2
3
4
|
<af:button text="Ok" id="b2" actionListener="#{TheBean.buttonActionListener}"/> <af:button text="Cancel" id="b3" immediate="true" actionListener="#{TheBean.cancelButtonActionListener}"/> |
|
1
2
3
|
public void cancelButtonActionListener(ActionEvent actionEvent) { getPopup().cancel();} |
Это оно!
| Ссылка: | ADF: Popup, Dialog и Input Components от нашего партнера JCG Евгения Федоренко в блоге ADF Practice . |