久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

使用 <ui:include> 的動(dòng)態(tài) ajax 導(dǎo)航

Dynamic ajax navigation with lt;ui:includegt;(使用 lt;ui:includegt; 的動(dòng)態(tài) ajax 導(dǎo)航)
本文介紹了使用 <ui:include> 的動(dòng)態(tài) ajax 導(dǎo)航的處理方法,對(duì)大家解決問題具有一定的參考價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧!

問題描述

假設(shè)我想在我的應(yīng)用程序中導(dǎo)航,并動(dòng)態(tài)包含不同的 facelet 頁面.我有一個(gè)這樣的 commandLink:

Suppose I want to navigate in my application, and include different facelet pages dynamically. I have a commandLink like this:

<h:commandLink value="Link" action="#{navigation.goTo('someTest')}">
    <f:ajax render=":content" />
</h:commandLink>

這就是我包含 facelet 的地方:

And this is where I include the facelet:

<h:form id="content">
    <ui:include src="#{navigation.includePath}" />
</h:form>

導(dǎo)航類:

public class Navigation {
    private String viewName;

    public void goTo(String viewName) {
        this.viewName = viewName;
    }

    public String getIncludePath() {
        return resolvePath(viewName);
    }
}

我見過類似的例子,但這當(dāng)然行不通.由于 ui:include 是一個(gè)標(biāo)記處理程序,因此在調(diào)用我的導(dǎo)航偵聽器之前很久就發(fā)生了包含.包括舊的 facelet,而不是新的.到目前為止,我明白了.

I have seen similar examples, but this doesn't work of course. As ui:include is a taghandler, the include happens long before my navigation listener is invoked. The old facelet is included, instead of the new. So far I get it.

現(xiàn)在到頭疼的部分:如何基于 actionListener 動(dòng)態(tài)包含 facelet?我試圖將 facelet 包含在 preRender 事件中,并在 RENDER_RESPONSE 之前包含一個(gè) phaseListener.兩者都有效,但是在事件偵聽器中,我不能包含包含其他 preRender 事件的 facelet,并且在 phaseListener 中,在包含的 facelet 中單擊一些后,我會(huì)得到重復(fù)的 Id.但是,檢查組件樹告訴我,根本沒有重復(fù)的組件.也許這兩個(gè)想法一點(diǎn)都不好..

Now to the headache part: How can I dynamically include a facelet, based on an actionListener? I tried to include the facelet in a preRender event, and a phaseListener before RENDER_RESPONSE. Both work, but in the event listener I can't include a facelet which contains an other preRender event, and in the phaseListener I get duplicate Id's after some clicks in the included facelet. However, inspecting the component tree tells me, there are no duplicate components at all. Maybe these two ideas were not to good at all..

我需要一個(gè)解決方案,其中帶有 ui:include 的頁面或包含 facelet 的 Java 類不必知道將被包含的頁面,也不必知道確切的小路.以前有人解決過這個(gè)問題嗎?我該怎么做?

I need a solution, where the page with the ui:include, or the Java class which includes the facelet, doesn't have to know the pages, which will be included, nor the exact path. Did anybody solve this problem before? How can I do it?

我正在使用 JSF 2.1 和 Mojarra 2.1.15

I am using JSF 2.1 and Mojarra 2.1.15

重現(xiàn)問題所需的只是這個(gè) bean:

All you need to reproduce the Problem is this 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 中

And this in 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>

這足以產(chǎn)生這樣的錯(cuò)誤:

That's enough to produce an error like this:

javax.faces.FacesException: Cannot add the same component twice: topform:j_id-549384541_7e08d92c

推薦答案

對(duì)于OmniFaces,我也試過通過創(chuàng)建一個(gè) <o:include> 作為 UIComponent 而不是 TagHandler 執(zhí)行 FaceletContext#includeFacelet()encodeChildren() 方法.這樣,在恢復(fù)視圖階段會(huì)記住正確包含的 facelet,并且包含的??組件樹僅在渲染響應(yīng)階段發(fā)生變化,這正是我們想要實(shí)現(xiàn)的構(gòu)造.

For OmniFaces, I've also ever experimented with this by creating an <o:include> as UIComponent instead of a TagHandler which does a FaceletContext#includeFacelet() in the encodeChildren() method. This way the right included facelet is remembered during restore view phase and the included component tree only changes during render response phase, which is exactly what we want to achieve this construct.

這是一個(gè)基本的啟動(dòng)示例:

Here's a basic kickoff example:

@FacesComponent("com.example.Include")
public class Include extends UIComponentBase {

    @Override
    public String getFamily() {
        return "com.example.Include";
    }

    @Override
    public boolean getRendersChildren() {
        return true;
    }

    @Override
    public void encodeChildren(FacesContext context) throws IOException {
        getChildren().clear();
        ((FaceletContext) context.getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY)).includeFacelet(this, getSrc());
        super.encodeChildren(context);
    }

    public String getSrc() {
        return (String) getStateHelper().eval("src");
    }

    public void setSrc(String src) {
        getStateHelper().put("src", src);
    }

}

.taglib.xml中注冊(cè)如下:

<tag>
    <tag-name>include</tag-name>
    <component>
        <component-type>com.example.Include</component-type>
    </component>
    <attribute>
        <name>src</name>
        <required>true</required>
        <type>java.lang.String</type>
    </attribute>
</tag>

這適用于以下視圖:

<h:outputScript name="fixViewState.js" />

<h:form>
    <ui:repeat value="#{includeBean.includes}" var="include">
        <h:commandButton value="Include #{include}" action="#{includeBean.setInclude(include)}">
            <f:ajax render=":include" />
        </h:commandButton>
    </ui:repeat>
</h:form>

<h:panelGroup id="include">
    <my:include src="#{includeBean.include}.xhtml" />
</h:panelGroup>

以及以下支持 bean:

And the following backing bean:

@ManagedBean
@ViewScoped
public class IncludeBean implements Serializable {

    private List<String> includes = Arrays.asList("include1", "include2", "include3");
    private String include = includes.get(0);

    private List<String> getIncludes() {
        return includes;
    }

    public void setInclude(String include) {
        return this.include = include;
    }

    public String getInclude() { 
        return include;
    }

}

(此示例需要包含文件 include1.xhtml、include2.xhtmlinclude3.xhtml 位于相同的基本文件夾中主文件)

(this example expects include files include1.xhtml, include2.xhtml and include3.xhtml in the same base folder as the main file)

fixViewState.js 可以在這個(gè)答案中找到:h:commandButton/h:commandLink 在第一次點(diǎn)擊時(shí)不起作用,僅在第二次點(diǎn)擊時(shí)起作用.為了修復(fù) JSF 問題 790 導(dǎo)致視圖狀態(tài)在有多個(gè) ajax 表單可以更新彼此的父級(jí).

The fixViewState.js can be found in this answer: h:commandButton/h:commandLink does not work on first click, works only on second click. This script is mandatory in order to fix JSF issue 790 whereby the view state get lost when there are multiple ajax forms which update each other's parent.

另請(qǐng)注意,這樣每個(gè)包含文件在必要時(shí)都可以有自己的 <h:form>,因此您不必將它放在包含周圍.

Also note that this way each include file can have its own <h:form> when necessary, so you don't necessarily need to put it around the include.

這種方法在 Mojarra 中運(yùn)行良好,即使回發(fā)請(qǐng)求來自包含內(nèi)的表單,但它在 MyFaces 中很難失敗,初始請(qǐng)求期間已經(jīng)出現(xiàn)以下異常:

This approach works fine in Mojarra, even with postback requests coming from forms inside the include, however it fails hard in MyFaces with the following exception during initial request already:

java.lang.NullPointerException
    at org.apache.myfaces.view.facelets.impl.FaceletCompositionContextImpl.generateUniqueId(FaceletCompositionContextImpl.java:910)
    at org.apache.myfaces.view.facelets.impl.DefaultFaceletContext.generateUniqueId(DefaultFaceletContext.java:321)
    at org.apache.myfaces.view.facelets.compiler.UIInstructionHandler.apply(UIInstructionHandler.java:87)
    at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:49)
    at org.apache.myfaces.view.facelets.tag.ui.CompositionHandler.apply(CompositionHandler.java:158)
    at org.apache.myfaces.view.facelets.compiler.NamespaceHandler.apply(NamespaceHandler.java:57)
    at org.apache.myfaces.view.facelets.compiler.EncodingHandler.apply(EncodingHandler.java:48)
    at org.apache.myfaces.view.facelets.impl.DefaultFacelet.include(DefaultFacelet.java:394)
    at org.apache.myfaces.view.facelets.impl.DefaultFacelet.include(DefaultFacelet.java:448)
    at org.apache.myfaces.view.facelets.impl.DefaultFacelet.include(DefaultFacelet.java:426)
    at org.apache.myfaces.view.facelets.impl.DefaultFaceletContext.includeFacelet(DefaultFaceletContext.java:244)
    at com.example.Include.encodeChildren(Include.java:54)

MyFaces 基本上會(huì)在視圖構(gòu)建結(jié)束時(shí)釋放 Facelet 上下文,使其在視圖渲染期間不可用,從而導(dǎo)致 NPE,因?yàn)閮?nèi)部狀態(tài)具有多個(gè)無效屬性.但是,可以在渲染期間添加單個(gè)組件而不是 Facelet 文件.我真的沒有時(shí)間調(diào)查這是我的錯(cuò)還是 MyFaces 的錯(cuò).這也是為什么它還沒有出現(xiàn)在 OmniFaces 中的原因.

MyFaces basically releases the Facelet context during end of view build time, making it unavailable during view render time, resulting in NPEs because the internal state has several nulled-out properties. It's however possible to add individual components instead of a Facelet file during render time. I didn't really have had the time to investigate if this is my fault or MyFaces' fault. That's also why it didn't end up in OmniFaces yet.

如果您仍然在使用 Mojarra,請(qǐng)隨意使用它.但是,我強(qiáng)烈建議在同一頁面上對(duì)所有可能的用例進(jìn)行徹底測試.Mojarra 有一些與狀態(tài)保存相關(guān)的怪癖,可能在使用此構(gòu)造時(shí)會(huì)失敗.

If you're using Mojarra anyway, feel free to use it. I however strongly recommend to test it thoroughly with all possible use cases on the very same page. Mojarra has some state saving related quirks which might fail when using this construct.

這篇關(guān)于使用 &lt;ui:include&gt; 的動(dòng)態(tài) ajax 導(dǎo)航的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!

【網(wǎng)站聲明】本站部分內(nèi)容來源于互聯(lián)網(wǎng),旨在幫助大家更快的解決問題,如果有圖片或者內(nèi)容侵犯了您的權(quán)益,請(qǐng)聯(lián)系我們刪除處理,感謝您的支持!

相關(guān)文檔推薦

JSF 2: page redirect after ajax call(JSF 2:ajax 調(diào)用后的頁面重定向)
JSF Navigation with Ajax(使用 Ajax 進(jìn)行 JSF 導(dǎo)航)
AJAX and the Browser Back Button(AJAX 和瀏覽器后退按鈕)
How does Facebook keep the header and footer fixed while loading a different page?(Facebook 如何在加載不同頁面時(shí)保持頁眉和頁腳固定?)
AJAX / Jquery XML parse(AJAX/Jquery XML 解析)
jQuery XML error #39; No #39;Access-Control-Allow-Origin#39; header is present on the requested resource.#39;(jQuery XML 錯(cuò)誤“請(qǐng)求的資源上不存在‘Access-Control-Allow-Origin’標(biāo)頭.) - IT屋-程序員軟件開發(fā)技術(shù)分享社
主站蜘蛛池模板: 蜜桃免费一区二区三区 | 亚洲福利一区二区 | 蜜桃免费一区二区三区 | 九九免费视频 | 一级高清免费毛片 | 欧美精品在线一区二区三区 | 亚洲精品乱码久久久久久蜜桃 | 精品国产一区二区国模嫣然 | 欧美成人精品一区二区男人看 | 亚洲精品久久久一区二区三区 | 国产一区二区电影 | 午夜免费| 成年人在线观看视频 | 精品一二三区视频 | h片在线播放 | sese视频在线观看 | 亚洲精品久久久久avwww潮水 | 欧美日韩一区二区在线观看 | 日本精品视频一区二区 | 精品国产乱码久久久久久牛牛 | 日韩中文字幕视频在线观看 | 亚洲国产精品99久久久久久久久 | a级性视频 | 久久精品国产99国产精品亚洲 | 欧美综合一区二区 | 欧美精品久久久久久久久久 | 免费精品| 久久综合久久久 | 五月综合久久 | 亚洲国产91 | 国产精品一区二区三区免费观看 | 国产激情视频在线免费观看 | 国产一级精品毛片 | 亚州午夜精品 | 国产精品成人在线播放 | 91福利网| 新超碰97 | 草草影院ccyy | 欧美一区二区在线观看 | 久久综合伊人一区二区三 | 国产午夜精品一区二区 |