2016-02-16 2 views
0

Je travaille actuellement sur un projet GWT où nous utilisons les librairies Sencha GXT. J'essaie actuellement de créer un CurrencyField avec un format monétaire personnalisé. Voici quelques exemples de la façon dont je veux que mon format personnalisé monnaie:Sencha GXT Custom CurrencyFormat pour le champ de saisie

€ 123,45 
€ 98.765.432,10 
€ 400,00 

Donc, comme vous pouvez le voir, je veux un euro signe préfixe; un espace entre le symbole monétaire et la décimale; points pour mille séparateurs; et des virgules pour les décimales (et bien sûr deux décimales derrière la virgule).

Dans GXT, il semble toutefois qu'il n'est pas possible de créer votre propre format personnalisé. Je sais avec le java.text.NumberFormat que je peux faire quelque chose comme régulier ceci:

NumberFormat format = NumberFormat.getCurrencyInstance(); 
DecimalFormatSymbols formatSymbols = new DecimalFormatSymbols(); 
formatSymbols.setCurrencySymbol("€"); 
formatSymbols.setGroupingSeparator('.'); 
formatSymbols.setMonetaryDecimalSeparator(','); 
((DecimalFormat)format).setDecimalFormatSymbols(formatSymbols); 

En GXT cependant, le com.google.gwt.i18n.client.NumberFormat doit être utilisé pour la setFormat -method du NumberField<BigDecimal>. Je sais une certaine personnalisation peut être utilisé avec le CurrencyData comme ceci:

private CurrencyData createCurrencyData() { 
    // CurrencyData docs: http://www.gwtproject.org/javadoc/latest/com/google/gwt/i18n/client/CurrencyData.html 
    return new CurrencyData() { 

    @Override 
    public String getCurrencySymbol() { 
     return "€"; 
    } 

    @Override 
    public String getSimpleCurrencySymbol() { 
     return "€"; 
    } 

    @Override 
    public String getPortableCurrencySymbol() { 
     return "€"; 
    } 

    @Override 
    public String getCurrencyCode() { 
     return "EUR"; // ISO4217 for this currency 
    } 

    @Override 
    public int getDefaultFractionDigits() { 
     return 2; // Amount of decimal positions 
    } 

    @Override 
    public boolean isSymbolPrefix() { 
     return true; // true to place currency symbol before the decimal 
    } 

    @Override 
    public boolean isSymbolPositionFixed() { 
     return true; // true to use the same currency symbol position regardless of locale (determined by the isSymbolPrefix-method) 
    } 

    @Override 
    public boolean isSpacingFixed() { 
     return true; // true to put a space between the currency symbol and the decimal 
    } 

    @Override 
    public boolean isSpaceForced() { 
     return true; // true to use the same spacing regardless of locale (determined by the isSpacingFixed-method) 
    } 

    @Override 
    public boolean isDeprecated() { 
     return false; 
    } 
    }; 
} 

que j'utilise maintenant comme ceci:

NumberField<BigDecimal> currencyField = new NumberField<BigDecimal>(
    new NumberPropertyEditor.BigDecimalPropertyEditor()); 
currencyField.setFormat(NumberFormat.getCurrencyFormat(createCurrencyData())); 

cependant deux problèmes:

  1. Ce n'est pas entièrement personnalisé comment je le veux. Il accepte maintenant les entrées comme ceci: €123,456.78; au lieu de € 123.456,78 (aussi, même si le CurrencyData#isSpacingForced devrait apparemment être utilisé pour un espace entre le symbole monétaire et décimal, il ne fonctionne pas sur le NumberField ..)
  2. Quand je viens de taper un numéro régulier comme 400, il donne une erreur au lieu de formatage automatique de l'entrée utilisateur: 400 does not have either positive or negative affixes is not a valid number.

Répondre

0

changements apportés:

Nous maintenant placé les paramètres régionaux néerlandais dans notre fichier .gwt.xml:

<extend-property name="locale" values="nl_NL"/> 
<set-property name="locale" value="nl_NL"/> 
<set-property-fallback name="locale" value="nl_NL"/> 

Et nous utilisons un format personnalisé comme celui-ci:

final BigDecimalField currencyField = new BigDecimalField(); 
currencyField.setFormat(CustomNumberFormat.getCurrencyFormat()); 

Avec la CustomNumberFormat-class comme ceci:

import java.util.Map; 

import com.google.gwt.core.client.GWT; 
import com.google.gwt.i18n.client.CurrencyData; 
import com.google.gwt.i18n.client.CurrencyList; 
import com.google.gwt.i18n.client.NumberFormat; 
import com.google.gwt.i18n.client.constants.CurrencyCodeMapConstants; 

public class CustomNumberFormat extends NumberFormat { 

    private static CurrencyCodeMapConstants currencyCodeMapConstants = GWT.create(CurrencyCodeMapConstants.class); 
    private static char currencySymbol; 
    private static NumberFormat cachedCurrencyFormat; 

    /** 
    * Get the default currency format 
    * @return the default currency format 
    */ 
    public static NumberFormat getCurrencyFormat() { 
    if (cachedCurrencyFormat == null) { 
     cachedCurrencyFormat = getCurrencyFormat(CurrencyList.get().getDefault().getCurrencyCode()); 
    } 
    return cachedCurrencyFormat; 
    } 

    /** 
    * Get the currency format 
    * @param currencyCode the code to use 
    * @return the {@link NumberFormat} to use 
    */ 
    public static NumberFormat getCurrencyFormat(final String currencyCode) { 
    return new CustomNumberFormat(defaultNumberConstants.currencyPattern(), lookupCurrency(currencyCode), false, true); 
    } 

    /** 
    * Lookup the currency data 
    * @param currencyCode the currency code e.g. EUR 
    * @return the {@link CurrencyData} 
    */ 
    private static CurrencyData lookupCurrency(final String currencyCode) { 
    final CurrencyData currencyData = CurrencyList.get().lookup(currencyCode); 

    final Map<String, String> currencyMap = currencyCodeMapConstants.currencyMap(); 

    final String code = currencyData.getCurrencyCode(); 
    final String symbol = currencyMap.get(currencyCode); 
    final int fractionDigits = currencyData.getDefaultFractionDigits(); 
    final String portableSymbol = currencyData.getPortableCurrencySymbol(); 
    return toCurrencyData(code, symbol, fractionDigits, portableSymbol); 
    } 

    /** 
    * 
    * @param code the currency code e.g. EUR 
    * @param symbol the currency symbol e.g. the euro sign 
    * @param fractionDigits the number of fraction digits 
    * @param portableSymbol the portable symbol 
    * @return the {@link CurrencyData} to use 
    */ 
    public static native CurrencyData toCurrencyData(String code, String symbol, int fractionDigits, 
     String portableSymbol) /*-{ 
          //CHECKSTYLE:OFF 
          return [ code, symbol, fractionDigits, portableSymbol ]; 
          //CHECKSTYLE:ON 
          }-*/; 

    private boolean currencyFormat = false; 

    /** 
    * 
    * @param pattern the currency pattern 
    * @param cdata the {@link CurrencyData} 
    * @param userSuppliedPattern <code>true</code> if the pattern is supplied by the user 
    */ 
    protected CustomNumberFormat(final String pattern, final CurrencyData cdata, final boolean userSuppliedPattern, 
     final boolean currencyFormat) { 
    super(pattern, cdata, userSuppliedPattern); 
    this.currencyFormat = currencyFormat; 
    } 

    /* (non-Javadoc) 
    * @see com.google.gwt.i18n.client.NumberFormat#format(boolean, java.lang.StringBuilder, int) 
    */ 
    @Override 
    protected void format(final boolean isNegative, final StringBuilder digits, final int scale) { 
    super.format(isNegative, digits, scale); 
    if (this.currencyFormat) { 
     final char decimalSeparator = defaultNumberConstants.monetarySeparator().charAt(0); 
     if (digits.toString().endsWith(decimalSeparator + "00")) { 
     digits.delete(digits.length() - 3, digits.length()); 
     } 
     if (isNegative) { 
     digits.delete(digits.length() - 1, digits.length()); // Delete leading "-" 
     digits.insert(0, "- "); // Insert "- " at the front 
     } 
    } 
    } 

    /** 
    * Parse a String. The String does not start with the expected prefix so we add it first 
    * @param text the text to parse 
    * @param inOutPos an offset telling us 
    * @return the parsed value 
    * @throws NumberFormatException if the text cannot be parsed 
    */ 
    @Override 
    public double parse(final String text, final int[] inOutPos) throws NumberFormatException { 
    //add the positive prefix (euro-sign plus space) 
    final String temp = getPositivePrefix() + text; 
    //parse the adjusted string 
    final double val = super.parse(temp, inOutPos); 
    //now here is the tricky bit... during parsing the inOutPos offset was updated based on the modified String 
    //but a check is maded to see if the resulting offset is equal to the length of the String we have been passed 
    //so we need to update inOutPos by removing the length of the positive prefix 
    inOutPos[0] -= getPositivePrefix().length(); 
    return val; 
    } 
} 

Maintenant, nous obtenons les résultats suivants:

€ 123,45      when entering 123,45 
€ 98.765.432,10    when entering 98765432,1 
- € 400,00     when entering -400