2

我正在使用 Vaadin 14 + Java,我想在键入时显示一个包含货币值的文本字段,包括千位分隔符。

如果我将对象加载到表单和文本字段中,则会显示分隔符,但是每当我输入新值或更改现有值时,千位分隔符不会显示/不会更新,直到我将对象保存到数据库并再次得到对象。

我已经将 ValueChangeMode 设置为 EAGER,但我想转换器仅在从数据库写入/加载时才被应用。

如何在打字时即时插入/更新千位分隔符?

示例:当我输入“1000000”时,我希望文本字段在我输入第三个零之后更新为“1.000”,在下一个零之后更新为“10.000”,然后是“100.000”,最后是第六个之后的“1.000.000”最后一个零。

文本域:

money_tf = new TextField("Money in €");
money_tf.setSuffixComponent(new Span("€"));
money_tf.addThemeVariants(TextFieldVariant.LUMO_ALIGN_RIGHT);
money_tf.setValueChangeMode(ValueChangeMode.EAGER);

粘合剂

binder = new BeanValidationBinder<>(MyClass.class);
binder.forField(money_tf).withConverter(new PriceConverter()).bind("money");

我的价格转换器:

private static class PriceConverter extends StringToBigDecimalConverter {

    public PriceConverter() {
        super(BigDecimal.ZERO, "Cannot convert to decimal value.");
    }

    @Override
    protected NumberFormat getFormat(Locale locale) {

        final NumberFormat format = super.getFormat(locale);
        format.setGroupingUsed(true); // enabled thousand separators
        if (format instanceof DecimalFormat) {
            // Always display currency with two decimals
            format.setMaximumFractionDigits(2); 
            format.setMinimumFractionDigits(2);
        }
        return format;
    }
}
4

1 回答 1

0

我已经将 ValueChangeMode 设置为 EAGER,但我想转换器仅在从数据库写入/加载时才被应用。

这可行,但涉及服务器往返。如果您没有设置对后端的每个更改的自动提交,则数据库不会在每个字母上更新,只有当您显式调用 binder.writeBean(..) 并将更改提交到数据库时。在慢速网络上快速打字时,用户体验可能不是最好的。

如何在打字时即时插入/更新千位分隔符?

我理解您的问题,可以在客户端(即浏览器)中完成转换。答案是肯定的。对于简单的情况,您可以使用textField.setPattern(regexp)where regexpis a Stringwith 正则表达式模式。对于更复杂的场景,它当然需要一些 JavaScript 逻辑,但不用担心,目录中有TextField Formatter 插件,它包装了 Cleave JS 库并为此提供了很好的 Java API。

或者,您可以使用框架的BigDecimalFieldField组件,这也将输入限制为某些数字格式。该字段的值类型不是String,而是BigDecimal

于 2020-04-16T05:38:34.170 回答