包含JSF复合组件的div

时间:2013-11-21 22:42:22

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

我的应用程序中有许多复合组件,有时我需要引用这些组件作为一个整体。默认情况下,复合组件不会在其子组件上生成任何其他标记,因此,如果为复合组件提供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更新复合组件时,我得到一个&#34;找不到具有标识符&#34的组件;例外。有没有办法让JSF为我的复合组件自动生成有效的组件和容器?我真的不想生成两个包含div或spans(即在简单的html div周围添加一个h:panelGroup)只是为了让ajax工作。或者,有没有办法强制JSF允许组件上的动态ID?

编辑:

在回答BallusC的回答时,我已经编辑了示例代码,以便更清楚地了解组件的构建和使用方式,因为根据他的回答,我完全可以使用它。我正在做一些不允许的事情。

1 个答案:

答案 0 :(得分:2)

  

当我尝试让他们通过ID更新复合组件时,我得到一个&#34;找不到具有标识符&#34的组件;例外

很遗憾你没有表明你是如何做到这一点的,因为如果你在更新中使用了复合的客户端ID,它应该可以正常工作。复合本身:

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

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

<f:ajax render="myId" />

你最有可能以错误的方式做到了。例如。您忘记了:前缀,或者您使用了#{cc.id}而不是#{cc.clientId}等。据我所知,上述内容始终适用于目前发布的所有Mojarra 2.x版本。< / p>

另见:


  

或者,是否有办法强制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 的组件!它只对例如同一<h:outputText id="myID">内的<p:commandButton>旁边的<cc:implementation>

理解功能要求,但解决方案并不是那么好。您最接近的赌注是(ab)使用@this并在update中有条件地检查{<1}}:

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

有这样的东西

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