ui:在o:tree中重复无法按预期方式工作 [英] ui:repeat in o:tree not working as expected

查看:116
本文介绍了ui:在o:tree中重复无法按预期方式工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是"branches"的全方位o:tree ,其中每个分支都有具有属性颜色"的叶子列表",该属性在树中应是可编辑的.

I'm using a omnifaces o:tree of "branches" where each branch has a "list of leafs" with the attribute "color" which should be editable in the tree.

- 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")

添加/删除分支并将叶子添加到任何分支都可以正常工作,并且符合预期.同样,任何包含所有叶列表(显示具有正确值的color属性)的复杂树的渲染都像一个超级按钮.

Adding/removing branches and adding leafs to any branch works fine and as expected. Also the rendering of any complex tree including all the list of leafes (displaying of the color attribute with the correct value) works like a charme.

但是更改颜色或删除叶子(因此ui:repeat中的任何内容)只能按预期显示最后渲染的分支.

But changing the color or removing a leaf (so whatever is within the ui:repeat) only works as expected for the last rendered branch.

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

The "color" input fields for the other leafes/branches don't work at all and the delete leaf link within the ui:repeat also doesn't work as for the leaf attribute in removeLeaf(...) always the corresponding leaf from the last rendered branch gets passed. So in the above example clicking on delete for the yellow leaf from branch 0 will call removeLeaf(orange, branch 0) which will then oviously not delete anything as branch 0 has no orange leaf.

这是绑定到基本部分的代码-如果需要,可以提供其他任何内容:

This is the code strapped down to the essential part - anything else can be provided if needed:

<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>

我知道有问题,其中嵌套了ui:repeat在Mojarra 2.1.19上,我想情况并非如此.如果我将o:tree替换为在分支列表上进行迭代的ui:repeat,则实际上嵌套两个ui:repeats可以很好地工作.但是后来我显然失去了所需的树功能.我刚刚测试过以验证嵌套ui:repeat能否正常工作.

I know that there is some issue with nested ui:repeat but as I'm on Mojarra 2.1.19 I guess it's not the case here. And actually nesting two ui:repeats works fine if I replace o:tree by a ui:repeat which iterates over a list of branches. But then I obviously lost the tree functionality which I need. This I just tested to verify nested ui:repeats work properly.

此问题似乎类似于另一个问题 ,但并非如此完全一样...

This problem seems to be similar to another question but it's not exactly the same...

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

If I replace the the inner ui:repeat by a p:dataList (as suggested in some other answers to solve ui:repeat problems and also now in BalusC answer here) the removeLeaf() links will all work proper but still only color input fields of the last branch will be bound.

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

UPDATE: I now had a closer look when using the p:dataList. The POST content from the AJAX request which I got from my browsers developer tools looks good:

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()记录到控制台,最终结果如下:

The treeBean.save() method is just logging the whole Tree.toString() to console which ends up like this:

[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的了解还不够深,无法真正了解如何调查信息丢失的地方.

If the color had some value != null before, the value remains the same - so it doesn't get overriden by null. I'm not yet deep enough into JSF to really know how to investigate where the information gets lost on it's way.

(我最初在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示例项目此处我添加了一个甚至更简单的String属性(没有列表) )直接连接到效果很好的分支机构.)

(I initially used Mojarra 2.1.19 on JBoss EAP 6.2 + Primefaces 5.2 + Omnifaces 2.1 but also experience exactly the same on Mojarra 2.2.12, TomEE, Primefaces 5.3 + Omnifaces 2.2. The complete Maven Eclipse sample project can be found here I added even one more simple String attribute (no List) directly to the Branch which works fine.)

推荐答案

这确实是由<ui:repeat>中的状态管理错误引起的.它无法正确识别自己嵌套在另一个迭代器中,并且在父迭代器的每次迭代期间重新访问之前,顽固地清除了状态.它

This is indeed caused by a state management bug in <ui:repeat>. It didn't properly recognize itself being nested in another iterator and stubbornly clears out the state before being revisited during each iteration of the parent iterator. It only recognizes a parent UIRepeat or UIData, but that's it. The <o:tree> doesn't and can't extend from UIData, and the UIRepeat is unfortunately a implementation-specific class and thus can't be used publicly as long as you want to be independent from a specific JSF implementation (Mojarra, MyFaces, etc).

您最好的选择是将<ui:repeat>替换为真正的UIData组件,该组件具有更好的状态管理实现.我只是在这里尝试过,添加项目对<h:dataTable><p:dataList>来说对我来说很好.仅删除项目失败,并显示<h:dataTable>,因为它显示了错误的客户端ID.它没有考虑容器客户端ID. <p:dataList>在添加和删除项目的两种情况下都对我有用.仍然无法更新列表中任何绑定的输入字段的服务器端模型,如该答案的注释中详细讨论的那样.

Your best bet is to replace <ui:repeat> by a real UIData component which has a much better state management implementation. I just tried it here and adding items works just fine for me with <h:dataTable> and <p:dataList>. Only removing items failed with <h:dataTable>, because it rendered wrong client IDs. It's not taking into account the container client ID. The <p:dataList> worked for me in both cases of adding and removing items. Still updating the server side model of any bound input fields in the list fails as discussed in detail in the comments of this answer.

<p:dataList type="none">替换整个<ui:repeat>(不使用type,它将呈现<ul><li>)是您所能获得的最接近的方法.

Replacing the entire <ui:repeat> by a <p:dataList type="none"> (without type, it will render an <ul><li>) is the closest you can get.

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

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

World would have been much simpler if JSF offered a public UIRepeat-like (marker) interface which all those repeaters could just check for when they're about to manage the state.

这篇关于ui:在o:tree中重复无法按预期方式工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆