我有一个简单的要求:我<tr:table/>
的列数是动态的。我将有一个对象列表someBean.features
,它将确定渲染的列数。
以下图表应阐明我的要求。
在我给出的代码中,使用了JSTL <c:forEach/>
标记,这在JSF环境中使用时显然会产生问题。他们做过这样的事情:
<tr:table value="#{someBean.values}">
<tr:column headerText="Name">
<tr:outputText value="#{someBean.name}"/>
</tr:column>
<c:forEach var="col" items="#{someBean.features}">
<tr:column headerText="Column-#{col.id}">
<tr:outputText value="#{col.name}"/>
</tr:column>
</c:forEach>
</tr:table>
但是当我分析上面的代码时,上面someBean.getValues
标签输入的方法<tr:table/>
被调用了几千次,而不是大约20次。这 - 正如我想的那样 - 是因为<c:forEach/>
标记是一个编译时标记,其中<tr:*/>
是渲染时间标记。
所以,这就是我打算做的事情(用<c:forEach/>
替换<tr:iterator/>
:
<tr:table value="#{someBean.values}">
<tr:column headerText="Name">
<tr:outputText value="#{someBean.name}"/>
</tr:column>
<tr:iterator var="col" value="#{someBean.features}">
<tr:column headerText="Column-#{col.id}">
<tr:outputText value="#{col.name}"/>
</tr:column>
</tr:iterator>
</tr:table>
但是,出于某种原因,<tr:iterator/>
似乎不喜欢被置于<tr:table/>
内并且它永远不会被执行。
任何解决方案,提示,指南都将不胜感激。
哦,我们正在使用JSF 1.1和MyFaces Trinidad 1.0.13实现。
感谢。
答案 0 :(得分:1)
getter call是一种特别便宜的操作。如果你的getter按照他们的意图完成他们的工作,只返回bean属性,那么这真的不会有害。
这种担忧让我觉得你在getter方法中错误地做了一些昂贵的业务工作而不是构造函数或一些只在请求时调用一次的事件方法。你应该相应地修复它。 Getters不应该做任何业务工作或最高只是做一些延迟加载。
至于为什么<c:forEach>
有效且<tr:iterator>
没有用,这是因为JSTL标签在视图构建时运行,而不是在视图渲染时间内运行,而UIData
唯一有效的子项component是UIColumn
组件。基本上,当要构建视图时,所有JSTL标记都将运行,并且您最终会得到一个纯JSF视图,其中所有<tr:column>
已经在正确的位置。当要呈现视图时,所有JSF标记都将运行,最终会得到一个纯HTML结果,然后可以将其发送到浏览器。
答案 1 :(得分:1)
我认为(你可能已经知道了);只有这样才能编写扩展UIXTable并提供自定义标记处理程序来处理<tr:columns items="#{columns}">
并将列数组扩展为html列