使用ui重复

时间:2016-06-29 14:18:24

标签: jsf primefaces composite-component mojarra uirepeat

因此,经过几天的调试,我们最终能够重现复合组件ui:repeatp:remoteCommand之间的一些奇怪的交互,以及我们不理解的JSF中的部分状态保存。

方案

复合组件使用ui:repeat迭代对象列表。在每次迭代期间,包含另一个复合组件并传递参数。

<ui:composition (...)>
  <ui:repeat var="myVar" value="#{cc.attrs.controller.someList}">
    <namespace:myRemoteCommand someParam="SomeParam"/>

在包含的复合组件中,有一个自动运行p:remoteCommand使用组件界面中定义的参数调用方法。

<ui:component (...)>
  <p:remoteCommand actionListener="#{someBean.someMethod(cc.attrs.someParam)}"
                   autoRun="true"
                   async="true"
                   global="false">

但是,在someMethod(...)中设置断点时,会传递一个空字符串。仅当部分状态保存设置为 false 时才会出现此情况。

解决方案

我们尝试了几种解决方案,以下方案似乎有效(但我们不明白为什么,也无法预见可能发生的任何其他问题):

  • 我们可以将部分状态保存设置为true

  • 我们可以将复合组件模式更改为ui:include

  • 我们可以删除一个或两个复合组件,而是直接包含内容。

问题

为什么JSF会这样做?复合组件ui:repeat和参数传递之间的这种交互是什么,这取决于我们是否使用ui:include /部分状态保存?

我们使用的是Primefaces 5.3,Glassfish 4.1,Mojarra 2.2.12,Java 8.

1 个答案:

答案 0 :(得分:4)

你的代码很好。只是Mojarra的<ui:repeat>被打破了。您不是第一个面临与<ui:repeat>的州管理相关问题的人。

问题的根本原因是#{cc}<ui:repeat>需要访问树时无法使用<ui:repeat value>。实际上,null#{cc}。快速解决方法是明确推送UIRepeat#visitTree()方法中的pushComponentToEL(facesContext, null)。鉴于Mojarra 2.2.12,请在line 734之前添加以下行UIComponent compositeParent = getCompositeComponentParent(this); if (compositeParent != null) { compositeParent.pushComponentToEL(facesContext, null); }

popComponentFromEL(facesContext)

并在line 767之后添加以下行if (compositeParent != null) { compositeParent.popComponentFromEL(facesContext); }

UIRepeat

如果您不是从源代码构建Mojarra,请将整个source code /WEB-INF/classes复制到您的项目中,维护其包结构并在其上应用上述更改。 /WEB-INF/lib中的类具有比/lib和服务器<ui:repeat>中的类更高的类加载优先级。我至少创建了issue 4162来解决这个问题。

另一种方法是用MyFaces替换Mojarra,或用基于UIData的组件替换<h:dataTable>,该组件具有状态管理权限,例如<p:dataList><p:dataList type="none" var="myVar" value="#{cc.attrs.controller.someList}"> <namespace:myRemoteCommand someParam="SomeParam" /> </p:dataList> 。< / p>

{{1}}

您可能只想应用一些CSS来摆脱小部件样式(边框等),但那是trivial

另见: