flutterdart

How to format input currency (from right to left) on a TextField in Flutter?


In a TextField I have a initial text 0.00 then how can I format the typed value once the user start typing in Flutter? I'm currently usig the flutter_money_formatter package but I can't get the expected behaviour.

For example, I want the following behaviour if user types the number: 1.800.45:

When the user taps 1. We should have 0.01
When the user taps 8. We should display 0.18
When the user taps 0. We should display 1.80
When the user taps 0. We should display 1.800
When the user taps 4. We should display 1.800,4
When the user taps 5. We should display 1.800,45.

My current code:

    class _MoneyTextFormField extends StatelessWidget {
      TextEditingController _controller = TextEditingController();

      @override
      Widget build(BuildContext context) {
        return TextFormField(
          controller: _controller,
          style: TextStyle(color: context.primaryColor),
          keyboardType: TextInputType.number,
          inputFormatters: [
            TextInputFormatter.withFunction((oldValue, newValue) {
              // remove characters to convert the value to double (because one of those may appear in the keyboard)
              String newText = newValue.text.replaceAll(MoneyTextFormField._cents, '')
                  .replaceAll('.', '')
                  .replaceAll(',', '')
                  .replaceAll('_', '')
                  .replaceAll('-', '');
              String value = newText;
              int cursorPosition = newText.length;
              if (newText.isNotEmpty) {
                value = formatCurrency(double.parse(newText), fractionDigits: 0);
                cursorPosition = value.length;
              }
              return TextEditingValue(
                  text: value,
                  selection: TextSelection.collapsed(offset: cursorPosition)
              );
            }),
          ],
        );
      }
    }

The function to format the value:

      /// Format the giving value and return the value as String
      /// Note: the parameter should be a int or double
      static String formatCurrency(num value,{int fractionDigits = 2}) {
        ArgumentError.checkNotNull(value, 'value');
        return FlutterMoneyFormatter(
          amount: value.toDouble(),
          settings: MoneyFormatterSettings(
            thousandSeparator: '.',
            decimalSeparator: ',',
            fractionDigits: fractionDigits
          ),
        ).output.nonSymbol;
      }

Note: this is not a duplicate of this one because the solution does not work for Flutter.


Solution

  • I just found the solution for this using the Intl package. Just use the formatCurrency method bellow and everything will be fixed.

    Note: The value should always be in cents. That is why we divide it by 100 to give us the cents and pass the result into the formatter.

      static String formatCurrency(num value,{int fractionDigits = 2}) {
        ArgumentError.checkNotNull(value, 'value');
    
        // convert cents into hundreds.
        value = value / 100;
    
        return NumberFormat.currency(
          customPattern: '###,###.##',
            // using Netherlands because this country also
            // uses the comma for thousands and dot for decimal separators.
          locale: 'nl_NL'
        ).format(value);
      }