I have a problem when I use grail automatic databinding \"ex: Test t = new Test(params)\" with decimal delimiter on Double form field. After few search, I\'ve found that it
I have the same problem here. For example a user in Germany will usually enter a , (comma) as a decimal separator but obviously you cannot prevent him from entering a dot instead ;) Also if you fill the value from Javascript it's quite difficult to get a localized number. So I wrote this small helper method for the controller. It might not cover all possible scenarios, but I need it for entering GPS coordinates. Feel free to suggest improvements.
/**
* Replaces , in the param with . an converts it to a Double.
* @param paramName an array of paramater names
*/
private convertDicimalParamsToDouble(paramName) {
paramName.each { it
def val = params[it]
if(val) {
val = val.replace(",", ".")
try {
params[it] = Double.parseDouble(val)
} catch (NumberFormatException) {
//ignore
}
log.debug("Converted decimal param ${it} with value '${params[it]}' to new value '${val}'")
}
}
}
Then call it like this for example:
def save() {
convertDicimalParamsToDouble(["lat", "lng"])
...
I've been searching and trying for 2 days. I've finally chosen to define a custom PropertyEditorRegistar. This way, I can fix the Locale only for the Double field format. However, I don't think that it's the best solution because it will be applied to all my Double fields. But in the mean time it does the job pretty well. So if someone have a better solution, I will be glad to test it and update my code.
So this is how I set this up :
1 - Create a new groovy class that implements PropertyEditorRegistrar (if you already have one, just add the part of code contained by the method in the existing one)
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.beans.PropertyEditorRegistrar;
import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.beans.propertyeditors.CustomNumberEditor;
public class CustomDoubleRegistrar implements PropertyEditorRegistrar {
@Override
public void registerCustomEditors(PropertyEditorRegistry registry) {
//define new Double format with hardcoded Locale.ENGLISH
registry.registerCustomEditor(Double.class,
new CustomNumberEditor(Double.class,
DecimalFormat.getInstance(Locale.ENGLISH),true))
}
}
2- Define the custom registrar into the conf/spring/resources.goovy (if it's not already there of course)
beans = {
customPropertyEditorRegistrar(CustomDoubleRegistrar)
}
3- That's it, the Grails auto data binding will work fine
Test t = new Test(params);
//params contains many Double fields with dot '.' as decimal delimiter
Don't hesitate to post better solutions... Thanks
EDIT 1
Since Grails 2.3 this solution is no longer working. If you still want to use this solution, you have to add this configuration to the Config.groovy file
grails.databinding.useSpringBinder = true
Or implement one of the new DataBinding. I've tried few of them but nothing seems to solve the decimal delimiter issue. Thank you to post answer if you know how...
EDIT 2
Since Grails 2.4+ you can define your own ValueConverter to bypass the basic Locale validation. Note that you must remove the changes made in the initial post and in the EDIT 1. Here's how to implement the custom ValueConverter:
conf/spring/resources.groovy
// Place your Spring DSL code here
beans = {
"defaultGrailsjava.lang.DoubleConverter"(DoubleValueConverter)
}
class DoubleValueConverter implements ValueConverter {
public LongValueConverter() {
}
boolean canConvert(value) {
value instanceof Double
}
def convert(value) {
//In my case returning the same value did the trick but you can define
//custom code that takes care about comma and point delimiter...
return value
}
Class<?> getTargetType() {
return Double.class
}
}
For Grails 2.3+ you can properly override the default binder/converter, although it is not trivial or intuitive.
See my answer here: Binding real number values to Grails domain attributes (values sent by Dojo widgets)