假设我想在我的应用程序中导航,并动态包含不同的 facelet 页面。我有一个这样的commandLink:
<h:commandLink value="Link" action="#{navigation.goTo('someTest')}">
<f:ajax render=":content" />
</h:commandLink>
这就是我包含 facelet 的地方:
<h:form id="content">
<ui:include src="#{navigation.includePath}" />
</h:form>
导航类:
public class Navigation {
private String viewName;
public void goTo(String viewName) {
this.viewName = viewName;
}
public String getIncludePath() {
return resolvePath(viewName);
}
}
我见过类似的例子,但这当然行不通。与ui:include
标记处理程序一样,包含发生在我的导航侦听器被调用之前很久。包括旧的 facelet,而不是新的。到目前为止,我明白了。
现在到头疼的部分:如何基于 actionListener 动态包含 facelet?我试图将 facelet 包含在 preRender 事件中,并在 RENDER_RESPONSE 之前包含一个 phaseListener。两者都有效,但是在事件侦听器中,我不能包含包含其他 preRender 事件的 facelet,并且在 phaseListener 中,在包含的 facelet 中单击一些后,我会得到重复的 Id。但是,检查组件树告诉我,根本没有重复的组件。也许这两个想法一点都不好..
我需要一个解决方案,其中带有 的页面ui:include
或包含 facelet 的 Java 类不必知道将包含的页面,也不必知道确切的路径。以前有人解决过这个问题吗?我该怎么做?
我正在使用 JSF 2.1 和 Mojarra 2.1.15
重现问题所需的只是这个 bean:
@Named
public class Some implements Serializable {
private static final long serialVersionUID = 1L;
private final List<String> values = new ArrayList<String>();
public Some() {
values.add("test");
}
public void setInclude(String include) {
}
public List<String> getValues() {
return values;
}
}
这在您的索引文件中:
<h:head>
<h:outputScript library="javax.faces" name="jsf.js" />
</h:head>
<h:body>
<h:form id="topform">
<h:panelGroup id="container">
<my:include src="/test.xhtml" />
</h:panelGroup>
</h:form>
</h:body>
这在 text.xhtml 中
<ui:repeat value="#{some.values}" var="val">
<h:commandLink value="#{val}" action="#{some.setInclude(val)}">
<f:ajax render=":topform:container" />
</h:commandLink>
</ui:repeat>
这足以产生这样的错误:
javax.faces.FacesException: Cannot add the same component twice: topform:j_id-549384541_7e08d92c