После ошибки проверки последующие запросы ajax получают значения из компонентов пользовательского интерфейса, а не из Beans

В моем приложении на основе JSF 2 у меня есть форма, которая включает (среди других компонентов пользовательского интерфейса) некоторые флажки.

На флажках я зарегистрировал ajax-запросы, которые запускаются при их проверке. Ajax-запросы на самом деле просто обновят значение другого флажка в компоненте поддержки. В результате будет также установлен другой флажок (когда он будет перерисован - так как он будет принимать обновленное значение из компонента поддержки в фазе ответа рендеринга).

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

Насколько я понимаю, это используется для новой функции JSF 2, чтобы хранить только частичные изменения в дереве компонентов.

Я не понимаю, как это связано с этапом валидации? Почему в кэше есть значениеStateHelperкласс для моего флажка, когда проверка обнаружила ошибки?

Ответы на вопрос(1)

Решение Вопроса

Это известная проблема, которая подробно объясняется вэтот ответ, В двух словах, проблема вызвана тем, что недействительные компоненты, которые должны быть отображены<f:ajax render> но не были выполнены<f:ajax execute> остается в недействительном состоянии вместе с исходным значением. Когда JSF отображает входной компонент, JSF сначала проверит, не является ли переданное значениеnull и затем отобразите это, иначе это покажет значение модели. В основном вам необходимо сбросить представленное значение входных компонентов, которые должны быть отображены, но которые не были выполнены ajax.

Чтобы достичь этого, вы можете использоватьActionListener которыйbasically делает следующее:

UIViewRoot viewRoot = context.getViewRoot();
PartialViewContext partialViewContext = facesContext.getPartialViewContext();
Set<EditableValueHolder> inputs = new HashSet<EditableValueHolder>();

// First find all to be rendered inputs and add them to the set.
findAndAddEditableValueHolders(partialViewContext.getRenderIds(), inputs);

// Then find all executed inputs and remove them from the set.
findAndRemoveEditableValueHolders(partialViewContext.getExecuteIds(), inputs);

// The set now contains inputs which are to be rendered, but which are not been executed. Reset them.
for (EditableValueHolder input : inputs) {
    input.resetValue();
}

Это было сообщено какВыпуск JSF 1060 и полное и многократно используемое решение было реализовано вOmniFaces библиотека какResetInputAjaxActionListener (исходный кодВот и демонстрация демонстрацииВот).

 25 мая 2012 г., 13:19
Какую версию / версию JSF вы используете?
 Jens25 мая 2012 г., 11:05
Я просто добавил код для сброса значений входных компонентов прямо в том месте, где первый флажок устанавливает значение второго флажка (в моем компоненте поддержки). Как это:ResetInputAjaxActionListener resetter = new ResetInputAjaxActionListener(); resetter.processAction(null);  Тогда все работает нормально. Так что я думаю, мне просто нужно найти лучшее место для запуска сброса. (все еще интересно, почему, почемуActionListener не запускается запросом axaj, который срабатывает, когда флажок установлен.)
 Jens24 мая 2012 г., 22:24
Я перезапустил его, добавил источник омнифасов и установил точку останова, чтобы посмотреть, получится ли вообще. Он получает удар по обычным запросам, но не по запросу ajax, который запускается установкой флажка.
 24 мая 2012 г., 14:46
Это не ударил? Уверены ли вы? Вам может понадобиться перезагрузить сервер после редактирования лица лиц.
 Jens24 мая 2012 г., 13:25
Большое спасибо за ответ. Я уже включил вашу библиотеку omnifaces в мой проект (дляFullAjaxExceptionHandlerFactory). Так что было просто включитьResetInputAjaxActionListener в моемfaces-config.xml файл. Но это называется только вInvokeApplicationPhase который не поражен моим запросом ajax. Мой запрос ajax вызван<h:selectBooleanCheckbox> и там<f:ajax render="@this">, Но я подробнее остановлюсь на этом. Я просто быстро попробовал ваше предложение.

Ваш ответ на вопрос