JSF ViewState не обновляется при отправке 2 форм

У меня проблема с JSF 2. Я использую Mojarra 2.1.14 с Primefaces 3.1.4.

У меня есть страница с двумя формами: formA и formB. Каждая из этих форм содержит ViewState в скрытом поле ввода.

<h:form id="formA" binding="#{sessionBean.formA}">
    <h:commandButton value="formA" action="#{sessionBean.actionA}">
        <f:ajax/>
    </h:commandButton>
</h:form>

<h:form id="formB" binding="#{sessionBean.formB}">
    <h:commandButton value="formB" action="#{sessionBean.actionB}">
        <f:ajax/>
    </h:commandButton>
</h:form>

Пользователь отправляет formA с действием Ajax. Внутри действия Java я явно обновляю formA и formB (которые привязаны).

public void actionA(){
    FacesContext.getCurrentInstance().getPartialViewContext().getRenderIds().add(formA.getClientId());
    FacesContext.getCurrentInstance().getPartialViewContext().getRenderIds().add(formB.getClientId());
    System.out.println("action A!!");
}

public void actionB(){
    System.out.println("action B!!");
}

В ответах Ajax есть HTML-код для formA и formB (элемент) и ViewState.

JSF обновляет HTML-код formA и formB и устанавливает ViewState вызывающей формы: formA. formB не содержит ViewState.

Пользователь отправляет formB с действием Ajax. Поскольку ViewState не определен, postBack имеет значение false, а renderResponse устанавливается в значение true на этапе RESTORE, пропуская этап INVOKE APPLICATION: действие не вызывается. После того, как ответ VIEW_STATE обновлен и если пользователь подводит formB, вызывается действие.

Это ошибка или ограничение JSF 2? Или я что-то не так делаю?

Вы можете найти проект maven на GitHub: https://github.com/nithril/jsf-multiple-form

Заранее спасибо за помощь!


person Nicolas Labrot    schedule 01.02.2013    source источник
comment
Можете ли вы опубликовать код для этих двух форм и атрибутов обновления AJAX?   -  person partlov    schedule 02.02.2013
comment
Я собираюсь закончить небольшой проект maven   -  person Nicolas Labrot    schedule 02.02.2013
comment
Попробуйте явно добавить render=":formB" внутри тега f:ajax.   -  person partlov    schedule 02.02.2013
comment
Он работает, но я пока не понимаю, чем он отличается от getRenderIds().add(formB.getClientId()); На самом деле две формы находятся в 2 фрагментах файла xhtml, которые не видят друг друга. Только родительский компонент видит 2 формы.   -  person Nicolas Labrot    schedule 02.02.2013


Ответы (2)


Проблема, с которой вы столкнулись, связана с известной проблемой с библиотекой JSF JavaScript. Обходной путь — явно указать идентификатор клиента другой формы в атрибуте rendered тега f:ajax:

<h:form id="formA" binding="#{sessionBean.formA}">
  <h:commandButton value="formA" action="#{sessionBean.actionA}">
    <f:ajax render=":formB @form"/>
  </h:commandButton>
</h:form>

<h:form id="formB" binding="#{sessionBean.formB}">
  <h:commandButton value="formB" action="#{sessionBean.actionB}">
    <f:ajax render=":formA @form"/>
  </h:commandButton>
</h:form>

Подробнее об этом:

person partlov    schedule 01.02.2013
comment
Спасибо за Ваш ответ. Две формы xhtml слабо связаны. К сожалению, чтобы исправить эту проблему, я должен сильно соединить их. - person Nicolas Labrot; 02.02.2013
comment
В первой ссылке есть код JavaScript, который может исправить это, возможно, вам стоит сначала попробовать его. Вы используете простые лица, так что это должно работать. Зная подход BalusC, который, вероятно, работает. - person partlov; 02.02.2013
comment
Я протестировал скрипт BalusC, и он работает. Я использую простые лица, но это не исправляет случай, когда компонент обновляется с помощью Java. - person Nicolas Labrot; 02.02.2013

Существует альтернативный трюк, если вы используете MyFaces 2.0.x / 2.1.x, который будет корректно обновлять формы, добавляя следующий скрипт:

window.myfaces = window.myfaces || {};
myfaces.config = myfaces.config || {};
//set the config part
myfaces.config.no_portlet_env = true; 

См. JSF Ajax и множественные формы.

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

person lu4242    schedule 02.02.2013
comment
Спасибо за информацию. Я должен попробовать с моими лицами - person Nicolas Labrot; 02.02.2013