我有两个jsf页面。layout.xhtml和page.xhtml。布局如下:
<ui:composition>
<h:panelGroup id="menu" layout="block">
<h:outputText value="#{menuBean}" />
<h:form>
<ui:repeat var="menuItem" value="#{menuBean.menuItems}">
<button:menuItem label="#{msgs[menuItem.label]}" action="#{menuBean.selectItem(menuItem.label)}" update="#{update}" />
</ui:repeat>
</h:form>
</h:panelGroup>
<ui:repeat var="menuItem" value="#{menuBean.menuItems}">
<h:panelGroup layout="block" rendered="#{menuBean.selectedItemLabel eq menuItem.label}">
<ui:include src="#{menuItem.page}" />
</h:panelGroup>
</ui:repeat>
页面如下:
<h:panelGroup binding="#{page}" layout="block">
<ui:decorate template="../template.xhtml">
<ui:param name="menuBean" value="#{pageBean}" />
<ui:param name="update" value=":#{page.clientId}" />
</ui:decorate>
</h:panelGroup>
当我第一次渲染页面时,一切都很好(菜单项被渲染等)。单击任意按钮后,我得到Target Unreachable, identifier 'menuBean' resolved to null
。
有人能解释一下发生了什么,为什么menuBean
没有被再次分配,以及是否有其他方法可以实现这种事情(有一些通用布局页面,在那里传递一些对象并生成页面)吗?我的豆子由Spring管理。
更新:
我想这个问题在某种程度上与我的合成按钮有关,它看起来像这样:
<composite:interface name="menuItem">
<composite:attribute name="action" targets="button" />
<composite:attribute name="styleClass" />
<composite:attribute name="label" />
<composite:attribute name="update" />
<composite:attribute name="rendered" />
<composite:insertChildren />
</composite:interface>
<composite:implementation>
<h:commandButton id="button" value="#{cc.attrs.label}" style="width: 150px;" action="#{cc.attrs.action}"
rendered="#{empty cc.attrs.rendered ? true : cc.attrs.rendered}" styleClass="menu-item #{cc.attrs.styleClass}" type="button">
<f:ajax render="#{cc.attrs.update}" />
</h:commandButton>
</composite:implementation>
如果我用标准的h:commandButton替换标记,那么一切都可以完美地工作。我将对象传递到模板中,模板将传递的对象传递到组合中,但我肯定缺少一些东西。
我认为问题与bean的作用域有关。据我所知,您的pageBean后台bean具有请求范围。尝试更改更宽的范围(应该是ViewScoped的视图范围)。如果您使用CDI注释而不是JSF,那么您可以查看@ConversationalScope(或者您可以使用Luiggi指出的MyFacesCODI库)。
我面对BalusC的问题已经在他的博客上描述过了:http://balusc.blogspot.cz/2011/09/communication-in-jsf-20.html#ViewScopedFailsInTagHandlers
简单地说,在回发请求(ajax刷新按钮)的那一刻,传递到我的复合按钮中的bean并不存在。正如BalusC所指出的,解决方案可以是创建标准UIComponent,而不是使用复合快捷方式。