I am using BigDecimalFields, and IntegerFields with a Binder and I would like to the output to contain commas and guaranteed decimal places for currency. For BigDecimals, my output is currently like ‘10000.00’ where I would want ‘10,000.00’. For integers, my output is currently like ‘9999’ where I would want ‘9,999’.
Is there a setting or CSS style that I am missing?
Or a better field type for currency, commas, and decimals?
Or a way to add a number/decimal string formatter to BigDecimalFields?
Thanks,
Kevin
Note: At first, I was using doubles in TextFields with a StringToDoubleConverter. This produced commas in the output. I decided to attempt to use the stronger typed BigDecimalField but I lost the commas, gained prevention typing of alphabetic characters, and gained static 2 decimal places for pennies (even when 1.00). So, I can revert to TextFields if needed. Old code where fieldUSDAmount is a TextField:
binder.forMemberField(fieldUSDAmount).withConverter(new StringToDoubleConverter("Enter a dollar amount; no $ needed."));
You can create/extend your own StringToDoubleConverter, where you can define your desired NumberFormat to be used in its convertToPresentation or getFormat method.
Working great now. Thanks again. I’ve only been playing with Vaadin for ~3 weeks and I am loving it.
My currency converter solution, which is probably like 20 other solutions that are difficult to find due to magical search terms:
import com.vaadin.flow.data.binder.Result;
import com.vaadin.flow.data.binder.ValueContext;
import com.vaadin.flow.data.converter.Converter;
import java.math.BigDecimal;
import java.text.DecimalFormat;
/* Vaadin docs source:
https://vaadin.com/docs/v14/flow/binding-data/tutorial-flow-components-binder-validation/#implementing-the-converter-interface
*/
/**
* Converter that handles a simple situation for TextField to BigDecimal.
* Simple usage below.
*
* Declaration of TextField in class that extends PolymerTemplate:
* `@Id("textFieldWithUSDAmount") // backtick to escape the @ for JavaDoc
* private TextField textFieldWithUSDAmount;
*
* Binder declaration and attach converter to TextField:
* BeanValidationBinder<YourBeanClass> binder = new BeanValidationBinder<>(YourBeanClass.class);
* binder.forMemberField(textFieldWithUSDAmount).withConverter(new CurrencyConverter());
*/
public class CurrencyConverter implements Converter<String, BigDecimal> {
@Override
public Result<BigDecimal> convertToModel(String fieldValue, ValueContext context) {
// Produces a converted value or an error
try {
// remove undesired dollar signs and commas
String simpleString = fieldValue.replaceAll("[€$,]
", "");
// ok is a static helper method that creates a Result
return Result.ok(new BigDecimal(simpleString));
} catch (NumberFormatException e) {
// error is a static helper method that creates a Result
return Result.error("Enter a number.");
}
}
// number output format that inserts commas and guarantees two decimal places
/* NOTE: I insert a dollar sign icon at the start of the TextField with:
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
textFieldWithUSDAmount.setPrefixComponent(new Icon(VaadinIcon.DOLLAR));
*/
private static final DecimalFormat decimalFormat = new DecimalFormat("###,###,###,###,###.00");
@Override
public String convertToPresentation(BigDecimal bigDecimal, ValueContext context) {
// Converting to the field type should
// always succeed, so there is no support for
// returning an error Result.
return decimalFormat.format(bigDecimal);
}
}