【问题标题】:Containing div for JSF composite components包含 JSF 复合组件的 div
【发布时间】:2013-11-21 22:42:21
【问题描述】:

我的应用程序中有许多复合组件,有时我需要将这些组件作为一个整体进行引用。默认情况下,复合组件不会在其子组件上生成任何附加标记,因此如果您为复合组件提供 id 属性,它只会将该 id 附加到子组件的生成 id 上。我想通过 id 引用整个组件(即用于 jquery 操作)。 JSF 组件不允许在 id 属性中使用 EL,因此为了实现这一点,到目前为止,我一直将我的复合组件包装在纯 html div 中,如下所示:

<ui:component ...
xmlns:cc="http://java.sun.com/jsf/composite"
...>

<cc:interface componentType="myComponent">
    <cc:attribute name="process" type="java.lang.String" required="false" default="@form"/>
    <cc:attribute name="update" type="java.lang.String" required="false" default="@form"/>  
...
</cc:interface>

<cc:implementation>
    <h:outputStylesheet name="myComponent.css" library="css/components" target="head"/>
    <div id="#{cc.clientId}" class="myComponent #{cc.attrs.styleClass}">
        ... composite component implementation here ...     

    <p:dataTable id="note-history" styleClass="entity-notes-history" value="#{cc.notes}" var="note" paginator="true" paginatorAlwaysVisible="false" 
                                paginatorPosition="bottom" rows="5" rendered="#{not empty cc.notes}" rowStyleClass="#{note.noteBaseType.word}">
            ...

            <p:column rendered="#{note.noteBaseType == 'Warning' and not cc.attrs.displayOnly}" style="width: 8em;">
                <p:commandButton actionListener="#{cc.cancelSeverity(note.id)}" process="#{cc.attrs.process}" update="#{cc.attrs.update} update="note-history" value="Reduce Severity"/>
            </p:column>
        </p:dataTable>
    </div>

</cc:implementation>

组件的使用方式如下:

....
<ppa:myComponent id="myId" update="myId" />
....

不幸的是,如果我在复合组件中有任何 ajax(特别是来自 primefaces 的 p:ajax)调用,当我尝试让它们按 ID 更新复合组件时,我会收到“找不到具有标识符的组件”异常。有没有办法让 JSF 为我的复合组件自动生成有效的组件和容器?我真的很讨厌必须生成两个包含 div 或 span(即在纯 html div 周围添加一个 h:panelGroup)只是为了让 ajax 工作。或者,有没有办法强制 JSF 允许组件上的动态 id?

编辑:

针对 BallusC 的回答,我编辑了示例代码,以便更清楚地了解组件的构建和使用方式,因为鉴于他的回答,我完全有可能只是在做一些不允许的事情。

【问题讨论】:

    标签: ajax jsf jsf-2 primefaces composite-component


    【解决方案1】:

    当我尝试让他们按 ID 更新复合组件时,我得到一个“找不到具有标识符的组件”异常

    很遗憾,您没有说明您是如何做到这一点的,因为它应该可以正常工作,前提是您在包含在组合本身中的更新中使用组合的客户端 ID:

    <f:ajax render=":#{cc.clientId}" />
    

    或者,您只是在更新中使用了复合材料自己的 ID,该更新是在同一命名容器父级内的复合材料之外执行的:

    <f:ajax render="myId" />
    

    很可能你做错了。例如。您忘记了: 前缀,或者您使用了#{cc.id} 而不是#{cc.clientId} 等。据我所知,上述内容一直适用于迄今为止发布的所有Mojarra 2.x 版本。

    另见:


    另外,有没有办法强制 JSF 允许组件上的动态 id?

    您可以只在id 属性中使用EL,前提是它在视图构建期间可用,因此不仅在视图渲染期间可用。有关相关背景信息,另请参阅 JSTL in JSF2 Facelets... makes sense?


    更新根据您的问题更新,其中您最终展示了您如何尝试实现它;

    <ppa:myComponent id="myId" update="myId" />
    

    <p:commandButton ... update="#{cc.attrs.update}" />
    

    你实际上是在做一个

    <p:commandButton ... update="myId" />
    

    这基本上是在寻找一个ID为myId的组件组合本身的上下文中!它只会影响例如&lt;h:outputText id="myID"&gt; 在同一 &lt;cc:implementation&gt; 内的 &lt;p:commandButton&gt; 旁边。

    功能需求理解了,但解决方案不是很好。您最接近的赌注是(ab)使用@this 并有条件地检查update

    <ppa:myComponent id="myId" update="@this" />
    

    类似这样的东西

    <p:commandButton ... update="#{cc.attrs.update == '@this' ? ':'.concat(cc.clientId) : cc.attrs.update}" />
    

    【讨论】:

    • 请查看我的编辑。他们会改变你的答案吗?这可能是 primefaces ajax 实现的问题吗?
    • 如果需要更新页面上的组件和其他组件(),该怎么办?我认为没有 .replace 和 .contains el 函数(即使有也会很混乱)。这种情况是否可以通过在复合组件支持 bean 中具有一个 String 属性来生成适当的字符串,或者在 JSF 生命周期中的正确时间不可用?
    • 嗯.. 这个解决方案似乎仍然不起作用。我试了一下,我仍然得到同样的异常:找不到标识符为“:j_idt157:0:j_idt163:j_idt171:j_idt386:myId”的组件,引用自“j_idt157:0:j_idt163:j_idt171:j_idt386:myId:note-history:0 :j_idt408”。这个复合组件是否在主页上的 p:dataGrid 中(并且就此而言,嵌套在另一个复合组件中)?我知道我过去曾遇到过 p:data* 组件和 ajax id 的问题。
    • 从上一条评论中回答我自己的问题,是的,如果我将组件放在根目录下,您的解决方案确实有效,这似乎是主页上的布局方式的问题测试页面的级别。答案标记为已接受,但我很高兴听到您对使用 p:data* 组件解决问题的任何想法。
    • 这确实很痛苦。我希望 PrimeFaces 特定的 @parent 能够像在客户端中的 update="@parent" 和复合中的 update="#{cc.attrs.update}" 那样进行救援,但是当我对其进行测试时,由于某些不清楚的原因,它似乎在这个构造中不起作用。我没有时间/心情去调试它。
    猜你喜欢
    • 2018-07-09
    • 2011-06-27
    • 2013-03-23
    • 2013-04-22
    • 2011-06-04
    • 1970-01-01
    • 2017-06-27
    • 2016-10-31
    • 2012-01-09
    相关资源
    最近更新 更多