JSF: ui:include и (неработающая) область просмотра
У меня есть страница JSF с некоторыми общими элементами, а затем 4 части, которые динамически загружаются и включаются на основе различных действий пользователя. У меня есть bean-компоненты, которые инкапсулируют функциональность различных включений, и структура выглядит примерно так:
mainview.xhtml
--backed by--> mainViewBean (request scope)
--with managed property--> mainViewView (view scope)
include1.xhtml
--backed by--> include1Bean (request scope)
--with managed property--> mainViewBean
include2.xhtml
--backed by--> include2Bean (request scope)
--with managed property--> mainViewBean
include3.xhtml
--backed by (and with component bindings to)--> include3Bean (request scope)
--with managed property--> mainViewBean
include4.xhtml
--backed by--> mainViewBean
На главной странице просмотра каждое включение включается через серию условно визуализированных h: panelGroups, как описано BalusC в следующих вопросах:
/questions/46425528/kakuyu-oblast-ispolzovat-v-shablone-jsf-20-for-wizard/46425537#46425537
Bean-объект области видимости содержит некоторую различную информацию о представлении, касающуюся текущего состояния действий пользователя, элементов, которые он просматривает в настоящее время, и так далее.
Каждое из представленных представлений выполняет различные задачи с помощью сообщений ajax и non ajax. Моя проблема заключается в том, что определенные действия в определенных панелях, по-видимому, приводят к разрушению области видимости, и, похоже, для этого нет ни рифмы, ни причины. Я заранее прошу прощения за запутанный рабочий процесс, описанный ниже, но постараюсь быть максимально ясным.
Если я выполняю действия ajax в include3.xhtml, они отображают компоненты только внутри include, и я могу выполнять их весь день, и область просмотра остается. Если я выполню посты без Ajax, обновление обновит (и, возможно, добавит ранее не отрендеренный) include4.xhtml. Затем я могу впоследствии выполнить действие в любом из других включений.
Если я выполняю действие ajax в include1.xhtml, которое вызывает методы только в своем собственном компоненте поддержки и обновляет только свои собственные компоненты, область просмотра остается. Если я выполню действие ajax, которое вызывает метод в include3Bean и обновит div, содержащий include2.xhtml и include3.xhtml, область просмотра останется, и пока я продолжу выполнять действия в include1.xhtml, область просмотра останется. Как только я пытаюсь выполнить другое действие в одном из других включений, область просмотра уничтожается.
Как этот момент, я подумал про себя, что проблема должна быть в том, что я обновляю разные включения, кроме того, из которого вызывается действие. Но это не является проблемой (или, по крайней мере, единственной проблемой), как я сейчас объясню.
include2.xhtml имеет действие ajax, которое при запуске вызывает метод в mainViewBacking и обновляет div, содержащий include2.xhtml и include3.xhtml. Если я продолжу выполнять это действие или предприму любое другое действие в include2.xhtml (в том числе не в AJAX-действиях), все будет работать так, как ожидается, и область просмотра останется. Однако, если я впоследствии выполню действие в include3.xhtml, область просмотра будет уничтожена. Странно, что я могу выполнять действия в include1.xhtml, и они будут продолжать иметь доступ к области просмотра столько, сколько я хочу, но если я попытаюсь вернуться и выполнить действие в include2.xhtml или include3. xhtml, область просмотра снова теряется.
Я немного застрял на этом этапе, и я даже не уверен, как понять, что не так. Я предполагаю, что что-то в обновлении (и удалении или добавлении) включений приводит к потере области видимости, но из ранее связанных вопросов, похоже, это не должно быть проблемой, так как фактические значения src для пользовательского интерфейса Включения не генерируются динамически. И у меня есть частичное сохранение состояния для mainview.xhtml выключен.
Есть ли что-то в этих динамически отображаемых интерфейсах: включает в себя, что нарушает область видимости?
1 ответ
Изменить 2014-02-28:
Глядя на последнюю витрину omnifaces, я заметил, что BalusC реализовал скрипт, который должен решить эту же проблему и, вероятно, сделать это гораздо лучше, чем мой код ниже.
http://showcase.omnifaces.org/scripts/FixViewState
Оригинальный ответ:
Оказывается, это была ошибка в JSF, как описано BalusC здесь: http://balusc.blogspot.com/2011/09/communication-in-jsf-20.html
К сожалению, его решение почему-то не сработало для меня. В результате я написал свою собственную (немного более раздражающую) работу, которую я предоставлю здесь другим, если им это понадобится.
Я добавил следующий javascript на страницу mainview.xhtml:
var lastForm = null;
function getViewStateFromLastForm(callingElement){
var currentForm = $(callingElement).closest("form");
var formId = currentForm.attr("id");
if(lastForm != null ){
var viewState = $("#" + lastForm).children("[name='javax.faces.ViewState']").val();
currentForm.children("[name='javax.faces.ViewState']").remove();
$('<input/>').attr({
type: 'hidden',
id: 'javax.faces.ViewState',
name: 'javax.faces.ViewState',
autocomplete: 'off',
value: viewState
}).appendTo(currentForm);
}
lastForm = formId;
}
Тогда каждая кнопка на различных включенных страницах, которые отправляются на сервер, имеет вызов getViewStateFromLastForm(this);
в их атрибутах onclick.