将实数值绑定到 Grails 域属性(Dojo 小部件发送的值)

Posted

技术标签:

【中文标题】将实数值绑定到 Grails 域属性(Dojo 小部件发送的值)【英文标题】:Binding real number values to Grails domain attributes (values sent by Dojo widgets) 【发布时间】:2014-08-08 02:00:05 【问题描述】:

我将 Dojo 1.9 与 Grails 2.3.9 一起使用。

我在表单中使用的 Dojo NumberTextBox 小部件以固定格式(javascript 基本格式)将实数值(例如:12.56)设置到 html 表单输入字段中(但根据浏览器显示/编辑它们语言环境,因此用户总是能看到格式正确的数字)。

另一方面,Grails 期望输入字段根据浏览器区域设置进行格式化。

这会导致转换不匹配,结果是当浏览器区域设置不是英语时,Grails 会丢失小数位,并将记录错误地保存到数据库中。

我试图通过实现自定义 ValueConverter 并将其注册到应用程序上下文中来覆盖 Grails 中的值转换。

浏览器发送的请求正确包含真实值(“12.45”)

主要问题是我的转换器似乎根本没有使用。

如何注册它以覆盖默认的 Double 数据转换?


转换器:

package gefc.dojo.binding

import org.grails.databinding.converters.ValueConverter
import java.text.NumberFormat

/**
 * Converter which allows that the doubles arrive 
 */
class DojoDoubleValueConverter implements ValueConverter 

  NumberFormat fmt

  DojoDoubleValueConverter() 
    // The number format sent by Dojo components
    // English locale for the decimal separator
    fmt = NumberFormat.getInstance(Locale.ENGLISH);
    // no grouping
    fmt.setGroupingUsed(false);
  

  boolean canConvert(value)  value instanceof String 

  def convert(value) 
    Number n = fmt.parse(value)
    return n.doubleValue()
  

  Class<?> getTargetType() 
    return Double.class
  

我在应用程序上下文中的注册 (resources.groovy)

beans = 
  // Dojo components send real values in a fixed, ISO format, while Grails
  // expects them to be formatted according to client/browser locale
  // So we need to override real value conversions
  doubleConverter gefc.dojo.binding.DojoDoubleValueConverter

【问题讨论】:

可能相关***.com/questions/14877602/… 肯定是同样的问题。然而,似乎还没有解决方案(在 Grails 2.3.x 中)。问的人使用了旧的绑定框架,而我尝试使用 Grails 2.3 中引入的新绑定系统。 2.3.9 的手册并没有说要覆盖现有的转换器,只添加新的。 这可能会有所帮助:grails.1312388.n4.nabble.com/… 它基本上说您需要将转换器专门命名为“defaultDoubleConverter”以覆盖系统默认转换器。我会尽快测试并报告结果。 【参考方案1】:

此问题已在 Grails 2.4+ 中修复

我在使用 Grails 2.3.8 的 Long 和 Integer 转换器时遇到了类似的问题。 Grails 使用 LocaleAwareNumberConverter 将字符串如“123abc”转换为“123”。 所以我定义了自己的转换器并覆盖了resources.groovy中的bean定义

beans = 
    "defaultGrailsjava.lang.LongConverter"(LongValueConverter)
    "defaultGrailsjava.lang.IntegerConverter"(IntegerValueConverter) 


class LongValueConverter implements ValueConverter 


    public LongValueConverter() 
    

    boolean canConvert(value) 
        value instanceof String
    

    def convert(value) 
        return value?.toLong()
    

    Class<?> getTargetType() 
        return Long.class
    

【讨论】:

【参考方案2】:

我终于找到了解决办法。

主要问题是转换器 bean 的命名错误。处理 double/Double 的两个转换器必须如下调用(在 applicationContext 中):

“defaultGrailsdoubleConverter”(用于双精度) “defaultGrailsjava.lang.DoubleConverter”(用于双精度)

这有点令人困惑,因为“defaultDateConverter”以更简单的方式命名,我认为双转换器命名将与此一致。

第二个问题是,如果您想从插件(而不是应用程序项目)覆盖这些,那么您必须从 YourGrailsPlugin.doWithSpring() 进行注册,因为 resources.groovy 不会与插件一起打包。如果您想从应用程序项目本身进行覆盖,那么将它们放在 resources.groovy 中就可以了。

您可能还想确保在初始化 DataBinding 插件之后进行此注册,否则您的插件可能会先初始化,而 DataBinding 插件只会用默认值覆盖您的转换器注册。这可以通过在 YourGrailsPlugin.groovy 中宣布对 DataBinding 插件的软依赖来完成:

    def loadAfter = ['dataBinding']

【讨论】:

我无法让它为我工作 - 使用 Grails 2.3.11 并通过插件进行设置。我的双打仍然使用调用语言环境(例如“ES”)而不是“EN”来解释。我已将"defaultGrailsjava.lang.DoubleConverter"(EnglishValueConverter)defaultGrailsdoubleConverter(EnglishValueConverter) 添加到我的doWithSpring 中(我也尝试过完全限定的类名)。有什么想法吗? 抱歉,我终于搞定了。我绑定的 bean 使用了 Float(我第一次没有检查代码)。一旦我连接了一个“defaultGrailsjava.lang.FloatConverter”,它就起作用了。

以上是关于将实数值绑定到 Grails 域属性(Dojo 小部件发送的值)的主要内容,如果未能解决你的问题,请参考以下文章

Grails 命令对象数据绑定

WPF DataGrid 单元格绑定到域对象中属性的属性未更新

Grails 默认排序的“hasMany”域属性

Grails 应用程序中的 Dojo Fisheye

在另一个域类中查看 grails 域类属性

如何从 Grails 中的控制器访问域属性?