2

我正在 JSF 中制作我的第一个复合组件,但我被一个行为奇怪的重新渲染难住了。这是组件实现(它应该是一个弹出窗口):

    <composite:implementation>
    <h:outputScript name="nb-popup.js" library="js"/>
    <h:outputStylesheet name="nb-popup.compiled.css" library="style"/>
    <div id="#{cc.clientId}_container" class="nb_popup_container">
        <div style="width:#{cc.attrs.width};height:#{cc.attrs.height};" id="#{cc.clientId}" class="nb_popup">
            <div id="#{cc.clientId}_header" class="nb_popup_header">
                <span class="nb_popup_header_content">
                    <composite:renderFacet name="header"/>
                </span>
                <span class="nb_popup_header_controls">
                    <composite:renderFacet name="controls"/>
                </span>
            </div>
            <div id="#{cc.clientId}_content" class="nb_popup_content">
                <composite:insertChildren/>
            </div>
        </div>
    </div>
    <script>popup('#{cc.clientId}');</script>
</composite:implementation>

例如,假设我们有:

<nb:popup id="extract">
    test
</nb:popup>

生成的 HTML 没问题:

    <div id="extract_container" class="nb_popup_container">
        <div style="width:auto;height:auto;" id="extract" class="nb_popup">
            <div id="extract_header" class="nb_popup_header">
                <span class="nb_popup_header_content">
                </span>
                <span class="nb_popup_header_controls">
                </span>
            </div>
            <div id="extract_content" class="nb_popup_content">
              test

            </div>
        </div>
    </div>

现在假设我有一个按钮:

    <h:commandLink value="reload">
        <f:ajax render=":extract"/>
    </h:commandLink>

按下它后,我得到以下部分响应,其中实际内容显然不是它应该在的位置:

    <div id="extract_container" class="nb_popup_container">
        <div style="width:auto;height:auto;" id="extract" class="nb_popup">
            <div id="extract_header" class="nb_popup_header">
                <span class="nb_popup_header_content">
                </span>
                <span class="nb_popup_header_controls">
                </span>
            </div>
            <div id="extract_content" class="nb_popup_content">
            </div>
        </div>
    </div>
    <script>popup('extract');</script>
    test
]]>

现在假设我将 insertChildren 移动到标题:

            <div id="#{cc.clientId}_header" class="nb_popup_header">
                <span class="nb_popup_header_content">
                    <composite:renderFacet name="header"/>
                <composite:insertChildren/>
                </span>
                <span class="nb_popup_header_controls">
                    <composite:renderFacet name="controls"/>
                </span>
            </div>

初始负载再次应为:

            <div id="extract_header" class="nb_popup_header">
                <span class="nb_popup_header_content">
         test

                </span>
                <span class="nb_popup_header_controls">
                </span>
            </div>

但是在重新加载时,内容会再次移动:

            <div id="extract_header" class="nb_popup_header">
                <span class="nb_popup_header_content">
                </span>
                <span class="nb_popup_header_controls">
    test

                </span>
            </div>

知道在 ajax 重新渲染后可能导致 insertChildren 看似随机放置的原因是什么吗?

4

1 回答 1

6

正如 BalusC 在评论中所建议的那样,将 cc:insertChildren 包装在 ah:panelGroup 中似乎可行。例如这有效:

            <div id="#{cc.clientId}_content" class="nb_popup_content">
                <h:panelGroup>
                    <composite:insertChildren/>
                </h:panelGroup>
            </div>

这使我可以在复合组件中保留样式和 js(使用 target="head"),因此总体而言这是一个更好的解决方案。


由于 outputStylesheet 和 outputScript 标签,这是 Mojarra 中的一个错误。如果你添加 target="head" 你会得到实际的 IndexOutOfBoundExceptions。如果没有目标,它只会在回发时做一些奇怪的事情。

当前的解决方案是在主应用程序中包含样式表和脚本。但是,这部分否定了复合材料的可重用性。

相关未决问题:

于 2012-10-18T08:39:01.920 回答