В этой статье я хотел бы остановиться на очень распространенном случае использования 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 . |