1

是否有可能有一个具有 ui:repeat 的 JSF 组件,并且在 repeat 内部调用相同的组件?这是因为我正在构建问题树:

<cc:interface>
    <cc:attribute name="questions" required="true" />
    <cc:attribute name="renderQuestions" required="true" default="true" />
</cc:interface>

<cc:implementation>

    <c:if test="#{cc.attrs.renderQuestions}">
        <ui:repeat value="#{cc.attrs.questions}" var="q">
            <p:panelGrid columns="2">
                <h:outputLabel value="#{q.question}"></h:outputLabel>
                <p:selectBooleanButton onLabel="#{messages['commons.yes']}"
                    offLabel="#{messages['commons.no']}" onIcon="ui-icon-check"
                    offIcon="ui-icon-close" value="#{q.ok}">
                    <p:ajax update="@all"></p:ajax>
                </p:selectBooleanButton>
            </p:panelGrid>

            <cf:question renderQuestions="#{q.ok}" questions="#{q.children}" />

        </ui:repeat>
    </c:if>

</cc:implementation>

目前我有stackoverflow?

4

2 回答 2

4

使用视图构建时间标签而不是视图渲染时间标签来停止递归。组件树是在视图构建时构建的。该rendered属性不在视图构建期间评估,而是在视图渲染期间评估。因此,您的构造基本上将自身包含在无限循环中。您应该已经知道这StackOverflowError是由于递归太深以至于内存堆栈无法再处理它(通常大约 1000 次迭代)。

替换<h:panelGroup rendered>为 a <c:if test>,它将按预期工作。顺便说一句,renderQuestions可以通过省略对儿童的检查来简化。如果<ui:repeat>没有孩子,无论如何都不会渲染任何东西。

如果您碰巧在此构造中使用视图范围 bean 并且您正在使用 Mojarra 实现,那么请确保您至少升级到 2.1.18,因为在旧版本中将视图构建时间标记属性绑定到视图范围 bean 属性打破视图范围。

也可以看看:

于 2013-07-29T12:31:19.660 回答
0

根据 BalusC 的回答,我创建了一个这样的解决方案。

<composite:interface>
    [..]
    <composite:attribute name="level" required="true" default="0"/>
</composite:interface>
<composite:implementation>

        <c:if test="#{cc.attrs.level == 0}">
            <a4j:repeat value="#{cc.attrs.list}" var="subList" rendered="#{cc.attrs.list != null}">

                    <xx:recursiveComponent list="#{subList}" id="subComponent" level="1"/>

            </a4j:repeat>   
        </c:if>

</composite:implementation>

level 属性在构建时使用以避免无休止的递归,并且 a4j:repeat (或 ui:repeat 在您的情况下)的 renered 属性将在渲染时进行评估。

于 2014-11-02T12:26:58.210 回答