3

Im building a form with several fields and Im initializing their values with controllers. Some fields are pure text fields but others have a mask, like a phone and zipcode fields.

Once I put the field on focus and start to backspace to erase the last characters it works fine on the fields without a mask. Fields with a mask the entire content of the field is cleared.

I`m using Flutter 3 and the mask_text_input_formatter ^2.4.0.

Here is my code to reproduce the problem with two fields. If you run this code and put the focus on the name field you can backspace it and only the last characters will be cleared. But in the phone field this causes the entire field to be cleared.

import 'package:flutter/material.dart';
import 'package:mask_text_input_formatter/mask_text_input_formatter.dart';

final phoneMaskFormatter = MaskTextInputFormatter(mask: '(###) ### ####');

class Test extends StatefulWidget {
  const Test({Key? key}) : super(key: key);

  @override
  State<Test> createState() => _TestState();
}

class _TestState extends State<Test> {
  final _formKey = GlobalKey<FormState>();

  late TextEditingController _nameController;
  late TextEditingController _phoneController;

  var myData = {'name': 'William', 'phone': '(305) 786 1234'};

  @override
  void initState() {
    super.initState();
    _nameController = TextEditingController();
    _phoneController = TextEditingController();

    _nameController.text = myData['name']!;
    _phoneController.text = myData['phone']!;
  }

  @override
  void dispose() {
    super.dispose();
    _nameController.dispose();
    _phoneController.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Form(
          key: _formKey,
          child: Container(
            padding: EdgeInsets.all(50),
            child: Column(
              children: [
                Text('Name: ${myData['name']}'),
                Text('Phone: ${myData['phone']}'),
                SizedBox(height: 100),
                TextFormField(
                    controller: _nameController,
                    onChanged: (value) {
                      // do my stuff
                      setState(() {
                        myData['name'] = value;
                      });
                    }),
                TextFormField(
                    controller: _phoneController,
                    inputFormatters: [phoneMaskFormatter],
                    onChanged: (value) {
                      // do my stuff
                      setState(() {
                        myData['phone'] = value;
                      });
                    }),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

The only thing that worked for me now is removing the mask in the phone field.

  • This is happen, because you assign initial value to it. While you enter value and then do backspace it will work. – Khyati Modi Dec 23 '22 at 13:36
  • I need to set an initial value since this is a form and the user shall edit existing values. Removing the initial value is not an option for me. – Adriano Marqueze Dec 23 '22 at 14:20

1 Answers1

0

Use extended_masked_text: ^2.3.1 It is satisfying your requirements.

Declaration of _phoneController and than initialise same as you did.

MaskedTextController _phoneController =
      MaskedTextController(mask: '(000) 000 0000');

void initState() {
...
  _phoneController.text = myData['phone']!;
...
}

and remove inputFormatters: [numberController].

Khyati Modi
  • 630
  • 1
  • 9
  • 19