I am using Dojo 1.9 with Grails 2.3.9.
The Dojo NumberTextBox widget - that I use in my forms - sets real number values (e.g.: 12.56) in a fixed format (the JavaScript base format) into the HTML form input fields (but displays/edits them according to the browser locale, so the user always sees properly formatted numbers).
Grails on the other hand expects the input fields to be formatted according to the browser locale.
This results in a conversion mismatch and the effect is that Grails loses the decimal places when the browser locale is not English and saves the record incorrectly to the database.
I was trying to override the value conversion in Grails by implementing a custom ValueConverter and registering it in the application context.
The request sent by the browser contains the real value correctly ("12.45")
The main problem is that my converter doesn't seem to be used at all.
How do I register it to override the defaut Double data conversion?
The converter:
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
}
}
My registration in the application context (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
}
This issue is fixed in Grails 2.4+
I had similar issue with Long and Integer converter with Grails 2.3.8. Grails is using LocaleAwareNumberConverter which converts string like "123abc" to "123". So I defined my own converter and override the bean definition in resources.groovy
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
}
}
I have finally found the solution.
The primary problem was that, the naming of the converter beans was wrong. The two converters dealing with double/Double must be called the following (in the applicationContext):
This is slightly confusing since "defaultDateConverter" is named in a much more simple way and I thought the double converter naming will be consistent with that.
Secondary problem is that if you want to override these from a plugin (as opposed to the application project), then you must do the registration from YourGrailsPlugin.doWithSpring() since resources.groovy will not be packaged with the plugin. If you want to do the override from the application project itself, then placing them in resources.groovy is fine.
You may also want to ensure that this registration happens AFTER the DataBinding plugin has been initialized, otherwise your plugin may be initialized first and the DataBinding plugin simply overwrites your converter registration with the defaults. This may be done by announcing a soft dependency on the DataBinding plugin from YourGrailsPlugin.groovy:
def loadAfter = ['dataBinding']
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With