Small details that build taste in Flutter.

curated by Kamran BekirovKamran Bekirov

Format phone numbers for humans

994501234567 is a string. +994 50 123 45 67 is a phone number. Humans read digits in groups, so a formatted number is easier to check and harder to mistype.

Format it everywhere the user sees it, including while they type:

For a single country, a mask is enough. mask_text_input_formatter does it:

import 'package:mask_text_input_formatter/mask_text_input_formatter.dart';
  
final phoneNumberInputFormatter = MaskTextInputFormatter(
  mask: '+### ## ### ## ##',
  filter: {
    "#": RegExp(r'[0-9]'),
  },
  type: MaskAutoCompletionType.eager,
);

eager inserts the spaces as the user types, not one digit late.

Wire it into the field:

TextField(
  inputFormatters: [
    phoneNumberInputFormatter,
  ],
)

The same formatter also formats numbers coming from your backend, and deformats them back. A small extension makes both one call:

extension StringX on String {
  String get maskPhoneNumber {
    return phoneNumberInputFormatter.maskText(this);
  }
  
  String get unmaskPhoneNumber {
    return phoneNumberInputFormatter.unmaskText(this);
  }
}

Then, show it formatted:

Text(
  user.phoneNumber.maskPhoneNumber,
)

And send it raw:

api.updatePhone(
  controller.text.unmaskPhoneNumber,
)

One mask stops working when you add a country picker. Don't write a mask per country. See first if your country picker package ships a formatter. If not, phone_numbers_parser knows every country's format. Wrap it in a small TextInputFormatter with selected country's ISO code:

class PhoneInputFormatter extends TextInputFormatter {
  PhoneInputFormatter(this.isoCode);
  
  final IsoCode isoCode;
  
  @override
  TextEditingValue formatEditUpdate(
    TextEditingValue oldValue,
    TextEditingValue newValue,
  ) {
    // drop own spaces and pasted symbols
    final String digits = newValue.text.replaceAll(
      RegExp(r'[^0-9]'),
      '',
    );
  
    return TextEditingValue(
      text: PhoneNumberFormatter.formatNsn(digits, isoCode),
    );
  }
}
Kamran Bekirov
Kamran Bekirov

Want this level of care in your Flutter apps?

Work With Me