键入时带有千位分隔符的 Vaadin 14 文本字段格式

Vaadin 14 Textfield format with thousand separators while typing

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

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

我已经 EAGER 设置了 ValueChangeMode,但我想只有在写入/从数据库加载时才会应用转换器。

如何在打字时快速 insert/update 千位分隔符?

示例:当我键入“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;
    }
}

I set the ValueChangeMode already EAGER, but I suppose the converter only gets applied when writing / loading from the database.

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

How can I insert/update thousand-separators on the fly while typing?

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

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