Условно пропустить проверку, если выбран пустой f:selectItem в p/h:selectOneMenu

Родители :

<p:selectOneMenu id="parentList"
                 value="#{bean.selectedParent}"
                 converter="#{parentConverter}"
                 required="true">

        <f:selectItem itemLabel="Select" itemValue="#{null}"/>

        <f:selectItems var="parent"
                       value="#{bean.parentList}"
                       itemLabel="#{parent.parentName}"
                       itemValue="#{parent}"/>

        <p:ajax update="childrenList" listener="#{bean.setchildren}"/>
</p:selectOneMenu>

Дети :

<p:selectOneMenu id="childrenList"
                     value="#{bean.selectedchild}"
                     converter="#{childConverter}"
                     required="true">

        <f:selectItem itemLabel="Select" itemValue="#{null}"/>

        <f:selectItems var="child"
                       value="#{bean.childrenList}"
                       itemLabel="#{child.childName}"
                       itemValue="#{child}"/>
</p:selectOneMenu>

Управляемый компонент:

@Named
@ViewScoped
public class Bean implements Serializable {

    @Inject
    private Service service;

    private Parent selectedParent;
    private Child selectedChild;
    private List<Parent> parentList;
    private List<Child> childrenList;

    private static final long serialVersionUID = 1L;

    public Bean() {}

    @PostConstruct
    private void init() {
        parentList = service.getParentList();

        // Not necessary unless selectedParent is already available in edit mode.
        if(selectedParent != null) {
            childrenList = service.getChildrenListByParent(selectedParent);
        }
    }

    public void setChildren() {
        if(selectedParent != null) {
            childrenList = service.getChildrenListByParent(selectedParent);
        } else {
            childrenList = null;
        }
    }

    // Getters and setters.
}

Список дочерних элементов должен быть заполнен на основе их родителя, т. е. список дочерних элементов должен содержать только дочерние элементы, связанные с конкретным родителем.

Когда выбран первый родитель в родительском списке, список дочерних элементов должен быть сброшен до пустого, т. е. дочерние элементы не должны быть видны без своего родителя.

Поскольку в родительском списке есть обязательный валидатор поля, он вызывает валидацию. Когда выбран первый элемент в родительском списке, дочерний список не будет обновляться из-за required="true". Технически в этом нет ничего плохого, но наличие дочерних элементов без родителя может доставить конечным пользователям неприятный опыт.

Что должно произойти, так это то, что когда выбран первый элемент в родительском списке, он не должен вызывать проверку, т. Е. Проверка должна быть пропущена условно.

Один из способов сделать это — проверить, является ли сам selectedChild или childrenList нулевым/пустым. Такие как,

required="#{empty selectedChild or empty childrenList}"

Но это не кажется каноническим способом условного пропуска проверки в таких случаях.

Существует ли лучший способ пропустить проверку, когда выбирается первый элемент в родительском списке, чтобы дочерний список мог быть очищен вместе с родительским списком (проверка должна вызывать во всех других случаях. Например, когда сама форма отправляется либо синхронно, либо асинхронно)?


person Tiny    schedule 25.07.2015    source источник


Ответы (1)


По сути, вам нужна проверка, зависящая от действия. т.е. пропустить проверку, когда вызывается это конкретное действие <p:ajax>, а не другие действия.

К сожалению, это действительно не тривиально объявить в представлении. Для этого есть несколько приемов/обходных путей. Наиболее часто используемый из них - просто проверить, не вызывается ли конкретное действие.

Например. проверьте, вызывается ли нужная кнопка сохранения, определяя наличие ее идентификатора клиента в карта параметров запроса HTTP, доступная по адресу неявный объект EL #{param}:

<h:form>
    <p:selectOneMenu ... required="#{not empty param[save.clientId]}">
        ...
        <p:ajax ... />
    </p:selectOneMenu>
    <p:selectOneMenu ... required="true">
        ...
    </p:selectOneMenu>
    <p:commandButton binding="#{save}" ... />
</h:form>

Или проверьте, не вызывается ли собственный <p:ajax> компонента, определив, не совпадает ли собственный идентификатор клиента компонента с параметром HTTP-запроса с предопределенным именем javax.faces.source, представляющим источник запроса ajax (#{component} ниже — это неявная переменная EL, представляющая текущий UIComponent):

<h:form>
    <p:selectOneMenu ... required="#{param['javax.faces.source'] ne component.clientId}">
        ...
        <p:ajax ... />
    </p:selectOneMenu>
    <p:selectOneMenu ... required="true">
        ...
    </p:selectOneMenu>
    <p:commandButton ... />
</h:form>

Или проверьте, отправлена ​​ли родительская форма UIForm#isSubmitted(), который будет оценивать true только тогда, когда используется полная отправка формы, как в process="@form" (по умолчанию <p:ajax process> равно @this, что не вызывает отправку полной формы, а <p:commandButton process> по умолчанию равно @form, что, таким образом, вызывает отправить полную форму):

<h:form binding="#{form}">
    <p:selectOneMenu ... required="#{form.submitted}">
        ...
        <p:ajax ... />
    </p:selectOneMenu>
    <p:selectOneMenu ... required="true">
        ...
    </p:selectOneMenu>
    <p:commandButton ... />
</h:form>

Или без привязки формы путем ссылки на форму через UIComponent#getNamingContainer() (если вы знаете позицию в дереве компонентов; если форма, например, 2 именует родителей контейнера назад, используйте #{component.namingContainer.parent.namingContainer.submitted}):

<h:form>
    <p:selectOneMenu ... required="#{component.namingContainer.submitted}">
        ...
        <p:ajax ... />
    </p:selectOneMenu>
    <p:selectOneMenu ... required="true">
        ...
    </p:selectOneMenu>
    <p:commandButton ... />
</h:form>

Сделайте ваш выбор. Первое решение уже предлагалось несколько раз, так как его проще всего понять и настроить новичкам.

Смотрите также:

person BalusC    schedule 26.07.2015