Поверхности зависят от selectOneMenu и required = "true"

В моем приложении у меня есть три раскрывающихся меню (p:selectOneMenu), например A, B, C. Среди них два зависят, скажем B и C. Изменяя значение BI am, динамически загружая значения в C. Также там это текстовое поле. Значение текстового поля генерируется ajax, когда событие on-change запускается из этих трех выпадающих меню.

Вот xhtml:

<p:selectOneMenu id="customerMenu" value="#{adminController.activityDTO.customerId}" required="true" label="Customer Name" style="width: 200px">
    <f:selectItem itemLabel="Select One" itemValue="" />
    <f:selectItems value="#{adminController.customers}" var="customer" itemLabel="#{customer.customerName}" itemValue="#{customer.customerId}" />
    <p:ajax listener="#{adminController.generateActivityName}" update="activityId" />                       
</p:selectOneMenu>

<p:selectOneMenu id="activityTypeMenu" value="#{adminController.activityDTO.activityParentType}" required="true" label="Activity Type"
    style="width: 200px">
    <f:selectItem itemLabel="Select One" itemValue="" />
    <f:selectItems value="#{adminController.activityTypes}" var="activityType" itemLabel="#{activityType.parent}" itemValue="#{activityType.parent}" />
    <p:ajax listener="#{adminController.updateDependentActivity}" update="activitySubType" />
</p:selectOneMenu>

<p:selectOneMenu id="activitySubTypeMenu" value="#{adminController.activityDTO.activitySubType}" required="true" label="Activity Sub Type"
    style="width: 200px">
    <f:selectItem itemLabel="Select One" itemValue="" />
    <f:selectItems value="#{adminController.activitySubTypes}" var="activityType" itemLabel="#{activityType.name}" itemValue="#{activityType.id}" />
    <p:ajax listener="#{adminController.generateActivityId}" update="activityId" />
</p:selectOneMenu>

<p:inputText id="activityId" autocomplete="off" readonly="true" value="#{adminController.activityDTO.activityId}"
    label="#{adbBundle['admin.addActivityPanel.addActivityTable.activityId']}" required="true" />

activityTypeMenu и activitySubTypeMenu зависят от выбранного значения activityTypeMenu Я заполняю activitySubTypeMenu.

Теперь проблемы, с которыми я столкнулся, это:

  • Скажем, я выбрал "Внешние" и "Внутренние" в activityTypeMenu и по умолчанию "Выбрать один" . Если я выберу "Внешнее" из activityTypeMenu, activitySubTypeMenu будет иметь "Проект" и "Сервис". Но если я выберу по умолчанию "Выбрать один" , то activitySubTypeMenu все еще удерживает ранее динамически заполненные значения. Это связано с тем, что атрибут required="true" не поддерживает запуск бэкэнд-метода, из которого я загружаю динамическое значение.
  • Я попытался установить itemValue из <f:selectItem itemLabel="Select One" itemValue="" /> в #{null}, а затем бэкэнд-метод запускается при выборе опции "Выбрать один" , и я могу установить пустой список на activitySubTypes, и таким образом activitySubTypeMenu пусто. Но в этом случае required="true" становится бессмысленным. Я имею в виду, что у меня также есть кнопка сохранения и при нажатии этой кнопки без выбора какой-либо опции (которая выбирает "Выбрать один" ) из activityTypeMenu и activitySubTypeMenu не выбрасывает ValidatorException, а компоненты не получают стили из-за ошибки css класс прайс-листов.
  • Также, если я не устанавливаю itemValue из <f:selectItem itemLabel="Select One" itemValue="" /> в #{null}, то при переключении на выбранное значение по умолчанию ( "Выбрать один" ) не выполняется очистка activityId p:inputText. Если я использую #{null}, тогда я могу запустить метод бэкэнда, из которого я могу установить значение текстового поля для пустого.

Как решить эти проблемы и получить желаемый результат. Я хочу:

  • Если для параметра выбрано значение "Выбрать один" , зависимое меню будет пустым и текстовым полем.
  • Я хочу использовать атрибут required="true".

Ответ 1

Вы можете использовать EL в атрибуте required. Вы можете позволить желаемому выражению оценивать true только при нажатии на конкретную кнопку отправки или при отправке определенного значения компонента (и, следовательно, его идентификатора клиента, присутствующего в карте параметров запроса #{param}).

Следующий пример запуска должен делать то, что вам нужно.

<p:selectOneMenu binding="#{menu1}" ... required="#{not empty param[submit.clientId]}">
    ...                       
</p:selectOneMenu>
<p:selectOneMenu ... required="#{not empty param[menu1.clientId]}">
    ...                       
</p:selectOneMenu>
<p:commandButton binding="#{submit}" ... />

Таким образом, 1-е меню требуется только при нажатии кнопки основного представления формы (и, следовательно, не при запуске прослушивателей событий), а второе меню требуется только в том случае, когда 1-е меню имеет значение.