I have a big form that I need to reuse in multiple pages. So, I decided to create a
<ui:composition>
that contains the form and include it in some pages (page1.xhtml and page2.xhtml).
form.xhtml:
<ui:composition ...>
<!-- The form goes here -->
</ui:composition>
This form has a controller called FormController
.
In page1.xhtml and page2.xhtml I just include the form using a <ui:include>
tag:
<ui:include src="/WEB-INF/.../form.xhtml"/>
I need to initialize a property in the FormController bean, so, in page1.xhtml I decided to set an attribute with the Id that I need (for example 5):
<c:set var="id" scope="request" value ="5"/>
And in the controller I just get the value of this attribute:
@PostConstruct
public init() {
Long id = ((HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest()).getAttribute("id");
//Do some queries to the database
}
Until know, everything works fine. But in page2.xhtml the "initialization" of the bean property has to be done after an ajax request, so I used the following code:
<h:selectOneMenu ...>
<f:selectItems ...>
<f:ajax listener="#{otherBean.doSomething}" render="panel"/>
</h:selectOneMenu>
<h:panelGroup id="panel">
<c:set var="id" scope="request" value ="#{otherBean.id}"/>
<ui:include src="/WEB-INF/.../form.xhtml"/>
</h:panelGroup>
What is weird is that this works just the first time I select an element in the <h:selectOneMenu>
. The second time, the doSomething()
method is called but the panel is not rendered (I don't know why, you know why?), so I decided to explore the following alternative that works well in both pages, but I feel that it isn't a good solution:
#{bean.init(otherBean.id)}
<ui:include src="/WEB-INF/modules/company/company.xhtml"/>
As you see, I am just calling an init
method (before the <ui:include>
) with the argument I need. In the controller I just set the property and do the corresponding queries:
public init(Long id) {
this.id = id;
//Do some queries
}
What do you thing about this solution?