2013-02-14 11 views
9

Ho un problema quando utilizzo il databinding automatico Graal "ex: Test t = new Test (params)" con delimitatore decimale nel campo Double form. Dopo poche ricerche, ho scoperto che è relativo al browser Locale.Grails che associa i database con delimitatore decimale

Esempio: Se inserisco il numero con i decimali separati da un punto '3.45' non funziona (la parte decimale del numero è ignorata). Memorizza 3.0 nel mio database

Se eseguo lo stesso test ma utilizzando la virgola "3,45" per il separatore decimale, tutto funziona correttamente. Grails archivia 3.45 nel database.

Il problema è che nessuno immette il numero con il delimitatore di virgola. (anche il tastierino numerico immette un punto "." se impostato su fr_CA)

Ho già trovato alcune soluzioni come registrare l'editor di numeri personalizzato (un po 'doloroso quando si hanno molte app) o impostare il locale globale Resolver su en_US (quest'ultimo non si fa il lavoro perché perdo tutte le funzionalità di internazionalizzazione della mia app).

Quindi, qualcuno ha una soluzione semplice per risolvere questo problema?

utilizzando: Grails: 2.2.0 Browser: Google Chrome (locale fr_CA)

Grazie mille!

risposta

15

Ho cercato e provato per 2 giorni. Finalmente ho scelto di definire un PropertyEditorRegistar personalizzato. In questo modo, posso correggere le impostazioni internazionali solo per il formato di campo doppio. Tuttavia, non penso che sia la soluzione migliore perché verrà applicata a tutti i miei campi Double. Ma nel frattempo fa il lavoro abbastanza bene. Quindi, se qualcuno ha una soluzione migliore, sarò lieto di testarlo e aggiornare il mio codice.

Quindi questo è come ho impostato questa funzione:

1 - Creare una nuova classe Groovy che implementa PropertyEditorRegistrar (se ne avete già uno, basta aggiungere la parte di codice contenuto con il metodo in quella esistente)

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- Definire il registrar personalizzato nella conf/primavera/resources.goovy (se non è già presente naturalmente)

beans = { 
    customPropertyEditorRegistrar(CustomDoubleRegistrar) 
} 

3- Questo è tutto, il Grai ls dati auto vincolante funzionerà benissimo

Test t = new Test(params); 
//params contains many Double fields with dot '.' as decimal delimiter 

Non esitare a pubblicare soluzioni migliori ... Grazie

EDIT 1

Dal Grails 2.3 questa soluzione non funziona più. Se si desidera continuare a utilizzare questa soluzione, si deve aggiungere questa configurazione al file diConfig.groovy

grails.databinding.useSpringBinder = true

o implementare uno dei nuovi DataBinding. Ho provato alcuni di loro ma nulla sembra risolvere il problema del delimitatore decimale. Grazie per inviare una risposta se sai come ...

EDIT 2

Dal Grails 2.4+ è possibile definire il proprio ValueConverter di bypassare la convalida di base Locale. Si noti che è necessario rimuovere le modifiche apportate nel post iniziale e nel MODIFICA 1. Ecco come implementare l'ValueConverter personalizzato:

conf/primavera/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 
    } 
} 
+2

funziona! :), Grazie mille! – conca

+0

sto lavorando con Grails 3.3.1 e questa soluzione non funziona per i miei oggetti comando. anche @BingUsing non funziona. Non so perché cambiano il vecchio comportamento. il nuovo è disgustoso: / – pebbles

0

Ho lo stesso problema qui. Ad esempio, un utente in Germania di solito inserisce una (virgola) come separatore decimale, ma ovviamente non puoi impedirgli di inserire un punto invece;) Inoltre, se inserisci il valore da Javascript è piuttosto difficile ottenere un numero localizzato. Così ho scritto questo piccolo metodo di supporto per il controller. Potrebbe non coprire tutti gli scenari possibili, ma ne ho bisogno per inserire le coordinate GPS. Sentiti libero di suggerire miglioramenti.

/** 
    * 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}'") 
      } 
     } 
    } 

Poi chiamare in questo modo, ad esempio:

def save() {   
    convertDicimalParamsToDouble(["lat", "lng"]) 
    ... 
Problemi correlati