JSF 2.0: как пропустить проверку bean-компонента JSR-303? - PullRequest
12 голосов
/ 31 января 2011

Как пропустить проверку JSR-303 Bean с помощью JSF при нажатии кнопки?

Немного длинный вопрос, чтобы объяснить несколько подходов ... Рассмотрим список в форме:

<h:form id="form">
    <h:commandButton value="Add row">
        <f:ajax execute="foo" listener="#{bean.add()}" render="foo" />
    </h:commandButton>
    <h:dataTable id="foo" var="foo" value="#{bean.foos}">
        <h:column>
            Name: <h:inputText id="field" value="#{foo.name}" required="true" />
            <h:messages for="field" />
        </h:column>
        <h:column>
            <h:commandButton value="Remove">
                <f:ajax execute=":form:foo" listener="#{bean.remove(foo)}" render=":form:foo" />
            </h:commandButton>
        </h:column>
    </h:dataTable>
</h:form>

Когда пользователь нажимает добавить или удалить строку, действие должно выполняться без проверки.Проблема в том, что JSF повторно отображает весь список и пытается его проверить.Если есть черновые изменения, которые не проверяются, возникают ошибки проверки, и метод слушателя никогда не вызывается (поскольку неудачная проверка предотвращает это).Однако добавление immediate="true" в f: ajax позволяет методу выполняться независимо от ошибок валидации.Тем не менее, ошибки проверки все еще происходят и отображаются здесь.

Я вижу два варианта:

1) Использовать немедленный = "истина" и не отображать ошибки проверки

Для не-validating кнопки, установите немедленное = "true" и для h: сообщения делают:

<h:messages rendered="#{param['SHOW_VALIDATION']}" />

Затем установите кнопку Save (которая должна фактически пытаться сохранить форму), чтобы отправить этот параметр:

<h:commandButton>
    <f:param name="SHOW_VALIDATION" value="true" />
</h:commandButton>

Это вызывает проверку, но сообщения просто не отображаются, за исключением случаев, когда присутствует параметр SHOW_VALIDATION.

2) Условно объявить проверку в фасетах:

<h:inputText>
    <f:validateRequired disabled="#{!param['VALIDATE']}" />
</h:inputText>

И Сохранить-button:

<h:commandButton>
    <f:param name="VALIDATE" value="true" />
</h:commandButton>

Это приводит к проверке полей только при наличии параметра VALIDATE (= когда нажата кнопка Сохранить).

Но это похоже нахаки.Как я могу просто использовать JSR-303 Bean Validation, но пропустить его при объявлении?

Ответы [ 4 ]

9 голосов
/ 31 января 2011

Установите обработчики событий как immediate=true и позвоните FacesContext.renderResponse() перед выходом из них.

ОБНОВЛЕНИЕ :

Изменения в вашем примере:

<h:form id="form">
    <h:commandButton value="Add row">
        <!-- Added immediate="true" to call bean.add() before validation phase -->
        <f:ajax execute="foo" listener="#{bean.add()}" render="foo" immediate="true"/>
    </h:commandButton>
    <h:dataTable id="foo" var="foo" value="#{bean.foos}">
        <h:column>
            Name: <h:inputText id="field" value="#{foo.name}" required="true" />
            <h:messages for="field" />
        </h:column>
        <h:column>
            <h:commandButton value="Remove">
                <!-- Added immediate="true" to call bean.remove() before validation phase -->
                <f:ajax execute=":form:foo" listener="#{bean.remove(foo)}" render=":form:foo" immediate="true"/>
            </h:commandButton>
        </h:column>
    </h:dataTable>
</h:form>

Изменения в вашем коде бина:

...
public void add() {
    // Your add() code
    ...
    // Added FacesContext.renderResponse() call to skip to render response phase
    FacesContext.getCurrentInstance().renderResponse();
}
...
public void remove() {
    // Your remove() code
    ...
    // Added FacesContext.renderResponse() call to skip to render response phase
    FacesContext.getCurrentInstance().renderResponse();
}
...
8 голосов
/ 09 февраля 2011

Вы можете отключить проверку bean-компонента с помощью тега f: validateBean с атрибутом disabled .

Пример:

<h:inputText value="#{bean.name}">
   <f:validateBean disabled="#{anotherBean.flag}"/>
</h:inputText>
2 голосов
/ 16 декабря 2011

Мы только что опубликовали решение этой проблемы. Полная информация здесь: http://www.springfuse.com/2011/12/15/skip-jsf-validation-depending-on-action.html

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

0 голосов
/ 03 апреля 2012

Положение: В коде страницы есть большая форма с большим количеством полей ввода. Есть несколько кнопок, каждая из которых указывает на отдельное действие в отдельном компоненте.

Решение, которое сработало для меня ...

  1. В коде страницы: добавьте immediate="true" к кнопке и укажите идентификатор для полей ввода, которые вы хотите использовать в компоненте.
 <p:inputText id="someHtmlInputId"
               maxlength="30" 
               value="#{beanName.attr}" />


 <p:commandButton id="someHtmlButtonId"
                   actionListener="#{beanName.doStuff}" 
                   value="Button Label"
                   ajax="false"
                   immediate="true"/>
  1. В методе bean doStuff получите параметры по имени фрагмента, прежде чем во входное имя JSF поместят некоторые другие идентификаторы, и полученное имя параметра может выглядеть так: someFormId: j_idt54: someHtmlInputId
Map<String, String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
if (params != null) {
  for (String k: params.keySet())
      if (k.indexOf("someHtmlInputId") != -1)
          params.get(k); // This is Your input parameter value waiting to be processed ;)
}
...