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

4

6

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.

Jae answered 15/6, 2020 at 15:30 Comment(1)
can you please answer one of my Questions its similar to this #73916363Haden
J
3

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);
  }
Jae answered 16/6, 2020 at 11:49 Comment(5)
Hi! i also had the same problem. Can you tell me where this function to be implement? in controller or inputFormatter?Headstone
Pass the returned value by this method in the formatter.Jae
Can you show the full implementation for this in the formatter?Broadcast
Hi, can you please provide complte code. It is a bit confusing how to use this solution and whereJorin
I've provided a standalone static function that you can simply copy & paste anywhere and use it, so I'm not sure what you mean by "complete code"Jae
G
4

You can use this way.

  bool isFirst = true; 


TextFormField(
                  controller: addAmountController,
                  keyboardType: TextInputType.number,
                  inputFormatters: <TextInputFormatter>[FilteringTextInputFormatter.digitsOnly],
                  onChanged: (value) {
                    String newValue = value.replaceAll(',', '').replaceAll('.', '');
                    if (value.isEmpty || newValue == '00') {
                      addAmountController.clear();
                      isFirst = true;
                      return;
                    }
                    double value1 = double.parse(newValue);
                    if (!isFirst) value1 = value1 * 100;
                    value = NumberFormat.currency(customPattern: '###,###.##').format(value1 / 100);
                    addAmountController.value = TextEditingValue(
                      text: value,
                      selection: TextSelection.collapsed(offset: value.length),
                    );
                  },
                )
Grotesque answered 15/6, 2021 at 9:33 Comment(0)
J
3

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);
  }
Jae answered 16/6, 2020 at 11:49 Comment(5)
Hi! i also had the same problem. Can you tell me where this function to be implement? in controller or inputFormatter?Headstone
Pass the returned value by this method in the formatter.Jae
Can you show the full implementation for this in the formatter?Broadcast
Hi, can you please provide complte code. It is a bit confusing how to use this solution and whereJorin
I've provided a standalone static function that you can simply copy & paste anywhere and use it, so I'm not sure what you mean by "complete code"Jae
E
0

Here an implementation using TextField and the solution from Pedro to divide value by 100 before format

TextField(
    autofillHints: null,
    keyboardType: TextInputType.number,
    controller: controller.expenseValueInputController,
    inputFormatters: [FilteringTextInputFormatter.digitsOnly],
    onChanged: (String textValue) {
        var valueNumber = double.parse(textValue.replaceAll(RegExp(r"\D"), "")) / 100;
        var fomattedValue = NumberFormat("#,##0.00", "en_US").format(valueNumber);
        controller.expenseValueInputController.value = TextEditingValue(
          text: fomattedValue,
          selection: TextSelection.collapsed(offset: fomattedValue.length),
        );
    }
)
Eupepsia answered 20/9 at 14:58 Comment(0)
Y
-1
$`import 'package:intl/intl.dart';`

                      onChange: (value) {
                            setState(() {
                              value = NumberFormat.currency(
                                      name: "", decimalDigits: 0)
                                  .format(int.parse(value));
                              _price.value = TextEditingValue(
                                text: value,
                                selection: TextSelection.collapsed(
                                    offset: value.length),
                              );
                            });
                          }
Yearbook answered 12/1, 2023 at 7:0 Comment(1)
Please avoid sharing code that does not compile and without describing why it works.Jae

© 2022 - 2024 — McMap. All rights reserved.