caseyryan / flutter_multi_formatter

A set of formatters for text and input fields. Not only it can format a phone number but also automatically detect a country dial code and the name of the country. It also can apply formatting for currencies e.g. you need to convert 100000 into a USD currency value representation. Add MoneyInputFormatter and you can get it e.g. like: $100,000.00 right on the fly or whatever you need. Just see the example of usage
https://pub.dev/packages/flutter_multi_formatter
Other
308 stars 75 forks source link

CurrencyInputFormatter - onValueChange reports incorrect value when cursor is at the end #115

Closed nizioleque closed 1 year ago

nizioleque commented 1 year ago

I am using CurrencyInputFormatter in the following way:

CurrencyInputFormatter(
  // ...
  mantissaLength: 2,
  onValueChange: (value) => print("NEW VALUE $value"),
)

When the cursor is at the end of the input (example here:) image

and I type something (for example 5), the value in the input does not change (which is correct), but I get this message:

NEW VALUE 123456.255

which is clearly incorrect and inconsistent with the content of the input.

Can you please fix this issue?

caseyryan commented 1 year ago

It's a bug of Flutter, I can't do anything with this. Sorry.

FayozbekJumabekov commented 4 days ago

i have this issue also. Can anyone find solution for this bug?

nizioleque commented 4 days ago

Here's the workaround that I came up with, it's a custom class that extends CurrencyInputFormatter:

class LocaleCurrencyInputFormatter extends CurrencyInputFormatter {
  factory LocaleCurrencyInputFormatter({
    required Locale locale,
    required Function(Fixed value) onValueChange,
  }) {
    final parameters = getCurrencyFormatParameters(
      locale: locale,
    );

    return LocaleCurrencyInputFormatter._(
      leadingSymbol: parameters.leadingSymbol,
      trailingSymbol: parameters.trailingSymbol,
      mantissaLength: parameters.mantissaLength,
      thousandSeparator: parameters.thousandSeparator,
      onValueChange: (value) {
        if (value.isNaN) return;

        // workaround for issue
        // https://github.com/caseyryan/flutter_multi_formatter/issues/115
        final correctValue =
            (value * pow(10, parameters.mantissaLength)).truncate() /
                pow(10, parameters.mantissaLength);

        final Fixed fixedValue = Fixed.fromNum(correctValue, scale: 2);
        onValueChange(fixedValue);
      },
    );
  }

  LocaleCurrencyInputFormatter._({
    super.leadingSymbol,
    super.trailingSymbol,
    super.mantissaLength,
    super.thousandSeparator,
    super.onValueChange,
  });
}

I use it together with my workaround for #134 like this:

return TextFormField(
  inputFormatters: [
    // workaround for issue
    // https://github.com/caseyryan/flutter_multi_formatter/issues/134
    FixZeroBeforeInputFormatter(shouldReplace),
    LocaleCurrencyInputFormatter(
      locale: Localizations.localeOf(context),
      onValueChange: (value) {
        if (shouldReplace[0]) {
          shouldReplace[0] = false;
          value = Fixed.zero;
        }
        widget.onChanged(value);
      },
    ),
    FixZeroAfterInputFormatter(shouldReplace),
  ],