2012-05-23 1 views
5

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

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

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

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

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

ответ

4

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

Для достижения этой цели, вы можете использовать ActionListener который в основном делает следующее:

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 issue 1060 и полное и многоразовое решение было реализовано в OmniFaces библиотеки, как ResetInputAjaxActionListener (исходный код here и демонстрация демонстрации here).

+0

Большое спасибо за ваш ответ. В любом случае, я уже включил ваш файл omnifaces lib в свой проект (для «FullAjaxExceptionHandlerFactory»). Поэтому было легко просто включить 'ResetInputAjaxActionListener' в файл' faces-config.xml'. Но это вызывается только в 'InvokeApplicationPhase', который не попадает в мой запрос ajax. Мой запрос ajax запускается с помощью '' и там ''. Но я поближе рассмотрю это. Я просто попробовал ваше предложение. – Jens

+0

Это не попало? Ты уверен? Возможно, вам придется перезапустить сервер после редактирования faces-config. – BalusC

+0

Я перезапустил его, и я добавил источник всемогущих и установил точку останова, чтобы узнать, попадает ли он вообще. Он попадает на обычные запросы, но не на запрос ajax, который запускается при выборе этого флажка. – Jens

Смежные вопросы