使用<ui:include>时设置控制器属性的正确方法

时间:2019-06-20 04:12:02

标签: jsf jsf-2.3

我有一个很大的表单,需要在多个页面中重复使用。因此,我决定创建一个
<ui:composition>,其中包含表单并将其包含在某些页面(page1.xhtml和page2.xhtml)中。

form.xhtml:

<ui:composition ...>
    <!-- The form goes here -->
</ui:composition>

此表单具有名为FormController的控制器。

在page1.xhtml和page2.xhtml中,我仅使用<ui:include>标签添加表单:

<ui:include src="/WEB-INF/.../form.xhtml"/>

我需要在FormController bean中初始化一个属性,因此,在page1.xhtml中,我决定设置一个具有所需ID的属性(例如5):

<c:set var="id" scope="request" value ="5"/>

然后在控制器中,我仅获得此属性的值:

@PostConstruct
public init() {
    Long id = ((HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest()).getAttribute("id");
    //Do some queries to the database
}

直到知道,一切正常。但是在page2.xhtml中,必须在ajax请求之后完成bean属性的“初始化”,所以我使用了以下代码:

<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>

奇怪的是,这仅在我第一次选择<h:selectOneMenu>中的元素时有效。第二次,调用doSomething()方法,但是不呈现面板(我不知道为什么,你知道为什么吗?),所以我决定探索以下两种在两个页面上都能正常使用的替代方法,但是我感觉这不是一个好的解决方案:

#{bean.init(otherBean.id)}
<ui:include src="/WEB-INF/modules/company/company.xhtml"/>

如您所见,我只是在使用需要的参数调用init方法(在<ui:include>之前)。在控制器中,我只是设置属性并执行相应的查询:

public init(Long id) {
    this.id = id;
    //Do some queries
}

您对此解决方案有何看法?

1 个答案:

答案 0 :(得分:0)

如果必须在开始时初始化表单,则可以使用

<f:metadata>
    <f:viewAction action="#{otherBean.initSomething('MYID2')}"/>
</f:metadata>

如果必须通过操作初始化表单

<h:commandButton action='#{otherBean.doSomething('MYID1')}'...>

<f:ajax listener="#{otherBean.doSomething('MYID')}" .../>