ui:在o中重复:树没有按预期工作

时间:2015-12-08 15:18:19

标签: jsf-2 tree omnifaces uirepeat

我正在使用omnifaces o:tree"分支"其中每个分支都有一个"叶子列表"使用属性" color"哪个应该可以在树中编辑。

- branch 0
  - leaf 0 (color = "green")
  - leaf 1 (color = "yellow")
- branch 1
  - leaf 0 (color = "purple")
  - branch 1_0
    - leaf 1 (color = "red")
    - leaf 2 (color = "orange")
    - leaf 3 (color = "brown")

添加/删除分支并将叶子添加到任何分支都可以正常工作并且符合预期。此外,任何复杂树的渲染(包括所有叶子列表(显示具有正确值的颜色属性)都像魅力一样。

但是更改颜色或删除叶子(因此ui:repeat内的任何内容)仅对最后渲染的分支有效。

"颜色"其他leafes / branches的输入字段根本不起作用,ui:repeat内的删除叶链接也不起作用,因为removeLeaf(...)中的leaf属性总是对应的来自最后一个渲染分支的叶子被传递。 因此,在上面的示例中,单击分支0中黄色叶的删除将调用removeLeaf( orange ,分支0),然后由于分支0没有,因此显然不会删除任何内容橙叶。

这是严格要素的代码 - 如果需要,还可以提供其他任何内容:

<h:form>
  <o:tree value="#{treeBean.tree}" var="branchEntity" varNode="branchNode">
    <o:treeNode>
      <o:treeNodeItem>
        <ui:repeat value="#{branchEntity.leafList}" var="leaf">
          <h:panelGrid columns="2">     
            <p:inputText value="#{leaf.color}" />   
            <p:commandLink action="#{treeBean.removeLeaf(leaf, branchEntity)}" styleClass="ui-icon ui-icon-trash"
                        process="@form" update="@form" />               
          </h:panelGrid>
        </ui:repeat>    

        <p:commandLink action="#{treeBean.addLeaf(branchEntity)}" styleClass="ui-icon ui-icon-plus"
                process="@form" update="@form" />
        <o:treeInsertChildren />
      </o:treeNodeItem>
    </o:treeNode>
  </o:tree>
  <p:commandButton id="save" value="Save" action="#{treeBean.save}" process="@form" update="@form" />
</h:form>

我知道有一些issue有嵌套ui:repeat但是我在Mojarra 2.1.19上我想这不是这里的情况。实际上,如果我将ui:repeats替换为遍历分支列表的o:tree,则嵌套两个ui:repeat可以正常工作。但后来我显然失去了我需要的树功能。我刚测试验证嵌套ui:repeat是否正常工作。

此问题似乎与another question 相似,但它并不完全相同......

如果我用ui:repeat替换内部p:dataList(如解决ui:repeat问题的其他答案中所建议的那样,现在也在BalusC回答中)removeLeaf()链接将所有工作正常,但仍然只会绑定最后一个分支的颜色输入字段。

更新:我现在在使用p:dataList时仔细查看了一下。我从浏览器开发人员工具获得的AJAX请求中的POST内容看起来不错:

javax.faces.partial.ajax=true
javax.faces.source=hForm:save
javax.faces.partial.execute=hForm
javax.faces.partial.render=hForm
hForm:save=hForm:save
hForm=hForm
hForm:oTree:0:pDataList:0:color=green
hForm:oTree:0:pDataList:1:color=yellow
hForm:oTree:1:pDataList:0:color=purple
hForm:oTree:1_0:pDataList:0:color=red
hForm:oTree:1_0:pDataList:1:color=orange
hForm:oTree:1_0:pDataList:2:color=brown
javax.faces.ViewState=-6137230173999059936:-6718691551411872927

treeBean.save()方法只是将整个Tree.toString()记录到控制台,最终结果如下:

[Branch [leafList=[Leaf [color=null], Leaf [color=null]]],
Branch [leafList=[Leaf [color=null]]]
[Branch [leafList=[Leaf [color=red], Leaf [color=orange], Leaf [color=brown]]]]]

如果颜色有一些值!=之前为null,则值保持不变 - 因此它不会被null覆盖。我还没有足够深入JSF来真正了解如何调查信息丢失的方式。

(我最初在JBoss EAP 6.2 + Primefaces 5.2 + Omnifaces 2.1上使用了Mojarra 2.1.19,但在Mojarra 2.2.12,TomEE,Primefaces 5.3 + Omnifaces 2.2上也体验过完全相同。可以找到完整的Maven Eclipse示例项目here我直接向分支添加了一个简单的String属性(没有List),工作正常。)

1 个答案:

答案 0 :(得分:1)

这确实是由<ui:repeat>中的状态管理错误引起的。它没有正确地识别自己嵌套在另一个迭代器中,并且在父迭代器的每次迭代中重新访问之前固执地清除状态。它only会识别父UIRepeatUIData,但这就是它。 <o:tree>并不能UIData延伸,UIRepeat不幸是特定于实施的类,因此无法公开使用只要你想独立于特定的JSF实现(Mojarra,MyFaces等)。

您最好的选择是将<ui:repeat>替换为具有更好状态管理实施的真实UIData组件。我刚刚在这里尝试过,使用<h:dataTable><p:dataList>添加项目对我来说效果很好。仅使用<h:dataTable>删除项目失败,因为它呈现了错误的客户端ID。它没有考虑容器客户端ID。 <p:dataList>在添加和删除项目的两种情况下都适用于我。仍然更新列表中任何绑定输入字段的服务器端模型失败,详见本答复的评论。

<ui:repeat>替换整个<p:dataList type="none">(不使用type,它将呈现<ul><li>),这是您可以获得的最近值。

<p:dataList type="none" value="#{branchEntity.leafList}" var="leaf">
    ...
</p:dataList>

如果JSF提供了一个公共的UIRepeat - 类似(标记)接口,所有这些转发器可以在他们即将管理状态时进行检查,那么世界会变得更加简单。