如何停止递归复合组件以递归方式包含自身
Posted
技术标签:
【中文标题】如何停止递归复合组件以递归方式包含自身【英文标题】:How to stop recursive composite component from including itself recursively 【发布时间】:2013-07-29 04:40:30 【问题描述】:是否有可能有一个具有 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>
目前我正在使用 ***?
【问题讨论】:
理论上嵌套两个ui:repeat
标签是没有问题的。但是,这取决于您的 cf:question
标签的内容。
嗨,cf:question 的内容与上面的代码相同,它是呈现该视图的递归调用。目标是编写问题及其子项(如果有)。
那么,你 shouldn't rely in JSF declarative tags 在视图端进行了这种递归。您为什么不针对问题构建一个双重迭代?
不幸的是,我想要的是一个 n 层次的问题,这就是为什么双迭代行不通的原因。
【参考方案1】:
根据 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 属性将在渲染时进行评估。
【讨论】:
【参考方案2】:使用视图构建时间标签而不是视图渲染时间标签来停止递归。组件树是在视图构建时构建的。 rendered
属性不会在视图构建期间评估,而是在视图渲染期间评估。因此,您的构造基本上将自身包含在无限循环中。您应该已经知道 ***Error
是由递归引起的,该递归太深以至于内存堆栈无法再处理它(通常大约 1000 次迭代)。
将<h:panelGroup rendered>
替换为<c:if test>
,它将按预期工作。 renderQuestions
可以通过省略对子项的检查来简化。如果没有孩子,<ui:repeat>
无论如何都不会渲染任何东西。
如果您碰巧在此构造中使用了视图范围的 bean,并且您正在使用 Mojarra 实现,那么请确保您至少升级到 2.1.18,因为将视图构建时间标记属性绑定到视图范围的 bean 属性会在旧版本中会破坏视图范围。
另见:
JSTL in JSF2 Facelets... makes sense? - 解释“查看构建时间”与“查看渲染时间”【讨论】:
您好 Balus,感谢您的回复,但在您在上面指定的更改之后,我仍然有同样的错误。我正在更新上面的帖子。 显然表达式从未计算过false
。
似乎 renderQuestions="#q.ok" 不起作用,但打印 q.ok 显示“假”,因此它不应该渲染视图,但似乎确实会导致 *** ,奇怪。以上是关于如何停止递归复合组件以递归方式包含自身的主要内容,如果未能解决你的问题,请参考以下文章