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

Javascript 将实数值绑定到Grails域属性(Dojo小部件发送的值),javascript,grails,groovy,dojo,Javascript,Grails,Groovy,Dojo,我正在使用Dojo1.9和Grails2.3.9 我在表单中使用的Dojo NumberTextBox小部件以固定格式(JavaScript基本格式)将实数值(例如:12.56)设置到HTML表单输入字段中(但根据浏览器区域设置显示/编辑它们,因此用户始终可以看到格式正确的数字) 另一方面,Grails希望输入字段根据浏览器区域设置进行格式化 这会导致转换不匹配,结果是当浏览器区域设置不是英语时,Grails会丢失小数点,并将记录错误地保存到数据库中 我试图通过实现自定义ValueConvert

我正在使用Dojo1.9和Grails2.3.9

我在表单中使用的Dojo NumberTextBox小部件以固定格式(JavaScript基本格式)将实数值(例如:12.56)设置到HTML表单输入字段中(但根据浏览器区域设置显示/编辑它们,因此用户始终可以看到格式正确的数字)

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

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

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

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

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

如何注册它以覆盖defaut双数据转换


转换器:

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

我终于找到了解决办法

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

  • “defaultGrailsdoubleConverter”(用于双精度)
  • “defaultGrailsjava.lang.DoubleConverter”(用于Double)
这有点令人困惑,因为“defaultDateConverter”的命名方式要简单得多,我认为双转换器的命名方式将与此一致

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

您可能还希望确保在初始化数据绑定插件之后进行此注册,否则您的插件可能会首先初始化,而数据绑定插件只会用默认值覆盖转换器注册。这可以通过从YourGrailsPlugin.groovy中宣布对数据绑定插件的软依赖来实现:

    def loadAfter = ['dataBinding']

这个问题在Grails2.4+中得到了修复。

Grails2.3.8中的长整数转换器也有类似的问题。Grails使用LocaleAwareNumberConverter将类似“123abc”的字符串转换为“123”。 因此,我定义了自己的转换器,并覆盖resources.groovy中的bean定义

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
}
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
    }
}
bean={
“defaultGrailsjava.lang.LongConverter”(LongValueConverter)
“defaultGrailsjava.lang.IntegerConverter”(IntegerValueConverter)
}
类LongValueConverter实现ValueConverter{
公共价值转换器(){
}
布尔canConvert(值){
字符串的值实例
}
def转换(值){
返回值?.toLong()
}
类getTargetType(){
返回长类
}
}

可能有一定关系,这是同样的问题。然而,似乎还没有解决方案(在Grails2.3.x中)。询问的人使用了旧的绑定框架,而我尝试使用Grails2.3中引入的新绑定系统。2.3.9的手册没有提到覆盖现有转换器,只是添加了新的转换器。这可能会有所帮助:它基本上说,您需要将转换器命名为“defaultDoubleConverter”,以便覆盖系统默认转换器。我将尽快测试它并报告结果。我无法让它对我起作用-使用Grails2.3.11并通过插件进行设置。我的替身仍然使用呼叫区域(例如“ES”),而不是“EN”来解释。我已经将
“defaultGrailsjava.lang.DoubleConverter”(EnglishValueConverter)
defaultGrailsdoubleConverter(EnglishValueConverter)
添加到我的
doWithSpring
(我还尝试了完全限定类名)。有什么好主意吗?对不起,我终于成功了。我绑定到的bean使用了一个Float(我没有第一次检查代码)。有一次我连接了一个“defaultGrailsjava.lang.FloatConverter”,它就工作了。