【问题标题】:Grails 2.4.4 upgrade data binding issueGrails 2.4.4 升级数据绑定问题
【发布时间】:2015-01-15 19:20:09
【问题描述】:

我们在此处用于大型动态表单的一种模式是允许客户端编辑几乎整个图形,包括子图形,并且子图形的删除和添加是在 javascript 中处理的。失败的用例是当用户删除其中一个孩子的属性时,对于这个例子,我们会说第二个孩子的电子邮件地址被删除并且parm被发送为空。

示例类结构

域 X

  Long id
  String name
  SortedSet<Child> children

域子

  Long id
  Integer position // used to sort 
  String name (required)
  String email (required)

Parms 以这种方式命名:

 x.id = 1
 x.name = 'blah'
 x.children[0].id = 1
 x.children[0].position = 0
 x.children[0].name = 'childa0'
 x.children[0].email = 'child0@any.com'
 x.children[1].id = 2
 x.children[1].position = 1
 x.children[1].name = 'child1'
 x.children[1].email = ''

当前存储的值:

 x.id = 1
 x.name = 'blah'
 x.children[0].id = 1
 x.children[0].position = 0
 x.children[0].name = 'childa0'
 x.children[0].email = 'child0@any.com'
 x.children[1].id = 2
 x.children[1].position = 1
 x.children[1].name = 'child1'
 x.children[1].email = 'child1@any.com'

要更新的模式是:

浏览器

  • 用户编辑所有并提交更改
  • parms 如上所示发送,在此用例中,用户意外删除了所需的电子邮件地址(是的,在这种简单的情况下可以阻止提交,但有更广泛的验证规则,这只是一个说明问题的简单示例)

服务器

  • 使用 id parm 检索当前父域类
  • 对照编辑的版本检查当前存储的版本,并确保它没有改变
  • 以这种方式将所有参数应用于当前域对象:x.properties = parms.x

这就是它崩溃的地方。在 Grails 2.2.2 中,child[1] 的 email 属性被更新为空字符串,并且运行验证会捕获错误。 Grails 2.4.4 不会更新子值。我知道数据绑定发生了变化,也许这种变化有正当的理由,但我无法理解。这从 1.3.6 到 2.2.2 都有效。

需要注意的一点是,如果我不检索域类,而是使用传入的参数创建一个新实例,则所有子参数都设置正确。

X x = new X(params.x) 

这似乎表明了一些 Grails 问题,因为用户指南谈到这两种方法是相同的 - 一种用于新实例,另一种用于更新,但示例清楚地表明这两种方法都应处理索引子属性。

感谢任何帮助或想法!

【问题讨论】:

  • 看看这是否有帮助。 stackoverflow.com/questions/27974665/…
  • 谢谢 - 我的用例完全不同,但这让我也尝试创建一个自定义活页夹,这反过来又让我在我的代码中发现了一个问题。我没有在页面中隐藏孩子的 ID,这让我想知道它以前是如何工作的!我猜旧版本的 grails 只是根据下标 [0]、[1] 等将所有数据放在子项中。Grails 2.4.4 显然希望匹配 ID,这是有道理的。

标签: grails data-binding upgrade


【解决方案1】:

我在将应用程序从 2.2.4 升级到 2.4.4 时遇到了这个问题。

config.groovy 设置 grails.databinding.useSpringBinder = true

并将 grails-web-databinding-spring 添加到 pom 对我来说完美无缺。

显然这样做比重写所有绑定代码要少得多:-)

【讨论】:

    【解决方案2】:

    进一步研究 Grails 2.4.4 文档指出,如果它们被索引(即 [0]),它将按位置绑定集合。

    http://grails.org/doc/latest/guide/single.html#dataBinding

    标题为“数据绑定和多端关联”的部分指出,这些参数将被绑定,并且如果它们的索引大于当前集合,则将创建集合的新实例。这对我来说在 Grails 2.2.2 中是正确的,但在 2.4.4 中不是。

    但是,在“绑定到集合和映射”部分的文档中,它清楚地指出:“在更新集合中的现有元素时,分配给集合的映射必须具有 id 元素,这些元素代表设置”。

    如果您要升级到 Grails 2.4.4 并且有任何复杂的表单数据绑定,我建议您先查看那里以决定是否升级。由于数据绑定的这些变化,这已成为我们在 Grails 中遇到的最复杂的升级。

    对 2.4.4 的另一个失望是它声明您可以覆盖新绑定并回退到旧的弹簧绑定,但您不能超过 2.4 - 至少从我可以从其他人的帖子和我的尝试中收集到的信息。按照文档设置配置属性并添加所需的依赖项会导致启动运行时错误。

    【讨论】:

      【解决方案3】:

      显然,2.4.4 之前的旧版本 grails 会将子实例与参数进行位置匹配,即使用索引([0]、[1] 等)来匹配不关心实例 ID 的子实例匹配。新的绑定器确实希望实例的 ID 在绑定之前匹配。我从来没有意识到我没有将 ID 放在隐藏字段中,因为它总是可以正常工作。

      【讨论】:

        【解决方案4】:

        在迁移到 Grails 2.4.4(从 2.2.2)后,我遇到了类似的问题。经过大量阅读和搜索(您必须明确阅读 user2863513 帖子中的http://docs.grails.org/2.4.4/guide/single.html#dataBindingmencioned),我以非常简单的方式解决了它

        在我的应用程序中,我有嵌套的域关系。示例:

        class A {
        String name
        static hasMany = [b:B]
        }
        
        class B {
        String name
        static hasMany = [c:C]
        }
        
        class C {
        String name
        }
        

        由于表单的复杂性,C 类对象没有正确绑定。我已经解决了将 B 类上的 C 属性定义为 List 的问题(请记住,默认情况下,许多关系都实现为 Sets)。于是,我的 B 班改为:

        class B {
        String name
        static hasMany = [c:C]
        List c
        }
        

        瞧!一切都再次完美运行。

        【讨论】:

          猜你喜欢
          • 2014-12-28
          • 2015-09-10
          • 1970-01-01
          • 2015-02-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多