アプリケーションでナビゲートし、さまざまな 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 ではなく、古い facelet が含まれています。これまでのところ、私はそれを理解しています。
頭痛の部分に移りましょう: actionListener に基づいて facelet を動的に含めるにはどうすればよいでしょうか? facelet を preRender イベントに含めようとし、RENDER_RESPONSE の前に phaseListener を含めようとしました。どちらも機能しますが、イベント リスナーでは、他の preRender イベントを含む facelet を含めることはできません。また、phaseListener では、含まれている facelet で数回クリックした後に重複した ID を取得します。ただし、コンポーネント ツリーを調べると、重複するコンポーネントはまったくないことがわかります。たぶん、これらの2つのアイデアはまったく良くありませんでした..
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