null

Обновление компонента с атрибутом rendered в JSF

Одной из типовых ошибок, разработчика на JSF является неправильное использование атрибута update для тегов Primefaces или же атрибута render тега ajax. Давайте рассмотрим одну такую часто возникающую ситуацию.

 

В прекрасный солнечный типичный дождливый день к вам приходит коллега со словами: "Можешь взглянуть в мой код, у меня что-то не работает?".  Вас приводят к монитору и показывают код. Рассказывают о том, что у него есть какая-нибудь кнопка, которая вызывает метод какого-нибудь бина, а потом вжух и должно что-то произойти, перерисоваться, измениться режим просмотра и т.д., и т.п. Но, почему-то ничего не происходит, хотя метод вызывается и всё успешно делает, и все условия совпадают. 

В таких ситуациях я уже на автомате первым делом смотрю на атрибут update компонента. Вообще, неправильное использование process и update -- масса ошибок, с которыми приходится иметь дело постоянно. Но сейчас хочется рассказать про ситуацию, когда человек указывает в update компонент, на котором стоит атрибут условного рендеринга. Ниже пример кода, который илюстрирует данную ситуацию:

 <p:panel id="somePanel" rendered="#{someBean.isRender}">
                    <ui:include src="some.xhtml"/>
</p:panel>
<p:commandButton action="#{someBean.someMethod}" 
update="somePanel" />

Это наиболее простой пример, в котором допущена ошибка. После нажатия на кнопку, будет вызван метод, который, предположим меняет условия рендеринга компонента с id somePanel. Теперь оно стало true и вроде бы всё должно прекрасно, но никаких изменений на стороне пользователя не происходит. Почему?

Суть заключается в том, что update работает на клиентской стороне с помощью javascript'а. А как javascript находит компоненты, которые нужно обновить? Он находит их в DOM дереве. Но есть проблема, ведь на компоненте стоит условный рендеринг, а это, значит, что если компонент не должен рендериться, то возможности обратиться к нему попросту не будет, т.к. он в DOM отсутствует.

 

Чтобы избежать данной проблемы всегда следите за тем, что используете update на компонентах, на которых нет условного рендеринга. Для того, чтобы заработал пример кода выше, необходимо обернуть panel с id = "somePanel" в другой компонент и обновить его родителя, который точно будет находиться в DOM.

 

На этом откланяюсь.