2011-07-11 18 views
6

En una aplicación peatonal incorporada, que tienen un campo de texto del número de decimales:Puede hacer que un TextField <BigDecimal> acepte ambos y. como separador decimal?

TextField<BigDecimal> f = 
    new TextField<BigDecimal>("f", new PropertyModel<BigDecimal>(model, "share")); 

quiero que aceptar siempre ambos. (punto) y, (coma) como separador decimal (independientemente de de la configuración regional del navegador).

Para mostrando el valor, se utiliza la configuración regional del período de sesiones [que en nuestro caso se ve obligado a ser "fi" (-> coma)], pero aquí estoy interesado en lo que el campo acepta como entrada.

Mi pregunta es, ¿tengo que cambiar el campo a TextField<String>, y convertir al tipo de objeto de dominio (BigDecimal) manualmente? ¿O hay alguna forma de usar TextField<BigDecimal> (que permite, por ejemplo, utilizar el Validador mínimo de Wicket o RangeValidator) y aún así aceptar ambos separadores decimales?

+5

No tener la documentación conmigo en este momento, pero puede inscribirse convertidores a nivel mundial en su clase de aplicación. Así que puedes registrar tu propia implementación de Convertidor para BigDecimal y aceptar ambas variantes allí – bert

+0

@bert, ¡gracias! Leer * Wicket en acción * (p 163), esa podría ser, de hecho, la mejor manera de abordar esto ... Considera escribir eso como una respuesta, también. – Jonik

+2

Solo una palabra de advertencia: en algunos lugares, ambos caracteres pueden aparecer en el mismo número, es decir, '.' se usa para agrupar miles y', 'como separador decimal. Si desea un analizador de números universal, asegúrese de que su código pueda manejar números como '32.519.100,28'. – biziclop

Respuesta

12

Gracias al comentario de @ bert, y al libro Wicket in Action, encontré un enfoque que funciona. En la clase de aplicaciones especificar un convertidor de medida para BigDecimals:

@Override 
protected IConverterLocator newConverterLocator() { 
    ConverterLocator converterLocator = new ConverterLocator(); 
    converterLocator.set(BigDecimal.class, new CustomBigDecimalConverter()); 
    return converterLocator; 
} 

Y en el convertidor de costumbre, convertToObject debe ser anulado. NB: esto es suficiente para nuestras necesidades; ¡piense en sus requisitos y adapte según lo necesitado!

public class CustomBigDecimalConverter extends BigDecimalConverter { 

    @Override 
    public BigDecimal convertToObject(String value, Locale locale) { 
     // NB: this isn't universal & your mileage problably varies! 
     // (Specifically, this breaks if '.' is used as thousands separator) 
     if ("fi".equals(locale.getLanguage())) { 
      value = value.replace('.', ','); 
     } 
     return super.convertToObject(value, locale); 
    } 
} 

Editar: Offtopic, pero quiero documentar esto también. Necesitábamos nuestra aplicación para admitir una escala de 4 lugares decimales, y nuestro convertidor personalizado BigDecimal también resuelve ese problema.

@Override 
    public String convertToString(Object value, Locale locale) { 
     NumberFormat fmt = getNumberFormat(locale); 
     fmt.setMaximumFractionDigits(4); // By default this is 3. 
     return fmt.format(value); 
    } 

Después de esta personalización, como un número decimal 2.0005 se mostrará como 2,0005 en lugar de 2.

Cuestiones relacionadas