jsf – 使用ui:repeat的复合组件在调用方法中缺少参数值

因此,经过几天的调试,我们最终能够重现复合组件之间的一些奇怪的交互,ui:repeat,p: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 / partial state save而改变?

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

最佳答案
你的代码都很好.这只是Mojarra的< ui:重复>被打破.您不是第一个面临与< ui:repeat>的状态管理相关问题的人.

> Checkbox inside ui:repeat not refreshed by Ajax
> Dynamically added input field in ui:repeat is not processed during form submit
> Components are with the same id inside ui:repeat
> <h:form> within <ui:repeat> not entirely working, only the last <h:form> is processed
> Composite component with custom backing component breaks strangely when nested inside ui:repeat
> ui:repeat in o:tree not working as expected

问题的根本原因是< ui:repeat>目前无法提供#{cc}.需要访问树.有效地,< ui:重复值>一片空白.快速解决方法是在UIRepeat#visitTree()方法中明确推送#{cc}.给定Mojarra 2.2.12,使用pushComponentToEL(facesContext,null)在line 734之前添加以下行.

UIComponent compositeParent = getCompositeComponentParent(this);
if (compositeParent != null) {
    compositeParent.pushComponentToEL(facesContext, null);
}

并使用popComponentFromEL(facesContext)在line 767之后添加以下行.

if (compositeParent != null) {
    compositeParent.popComponentFromEL(facesContext);
}

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

另一种方法是用MyFaces替换Mojarra,或者替换< ui:repeat>通过基于UIData的组件获得状态管理权限,例如< h:dataTable>或< p:dataList>.

<p:dataList type="none" var="myVar" value="#{cc.attrs.controller.someList}">
    <namespace:myRemoteCommand someParam="SomeParam" />
</p:dataList>

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

也可以看看:

> Should PARTIAL_STATE_SAVING be set to false?

转载注明原文:jsf – 使用ui:repeat的复合组件在调用方法中缺少参数值 - 代码日志