2

I need to make a TextField that has a date filter (dd-mm-yyyy), I managed to create the filter using the dependency mask_text_input_formatter: ^1.0.6 like so

final TextEditingController _controller = TextEditingController();
var maskFormatter = new MaskTextInputFormatter(mask: '##-##-####');
...
child: TextField(
  controller: _controller,
  keyboardType: TextInputType.number,
  inputFormatters: [maskFormatter],
  onChanged: (text) {
    //
  },

so since I couldn't find a good way to mask the text to be a valid date (e.g. no 31-02-9299), I decided to do it manually in onChanged callback and update the text at some point, but just testing with a basic _controller.text = "1234"; shows the text "1234" and not "12-34".

what could be the issue?

om-ha
  • 1,441
  • 9
  • 20
El Jazouli
  • 2,600
  • 2
  • 20
  • 40
  • Did you try providing a regex filter? Like so: `var maskFormatter = new MaskTextInputFormatter(mask: '##-##-####', filter: { "#": RegExp(r'[0-9]') });` – om-ha Feb 20 '20 at 15:13
  • yeah I did that first but it allows any numbers so you can still put 88-99-0000 as input – El Jazouli Feb 21 '20 at 09:28
  • And why is that wrong? putting zeros in a number is perfectly normal. If you don't want zeros then try one of the following: A. **For no zeros at all** `var maskFormatter = new MaskTextInputFormatter(mask: '##-##-####', filter: { "#": RegExp(r'[1-9]') });` or B. **For prohibiting leading zeros only** `var maskFormatter = new MaskTextInputFormatter(mask: '++-##-####', filter: { "+": RegExp(r'[0-9]'), "#": RegExp(r'[1-9]') });` – om-ha Feb 22 '20 at 08:41
  • no I mean the date would be wrong, if you are able to set for example dd/mm/yyyy as 99/02/9182, there is no such thing as a 99 day month – El Jazouli Feb 25 '20 at 11:15
  • You can't do this with `mask_text_input_formatter` as it performs comparison char by char. See [this source](https://github.com/siqwin/mask_text_input_formatter/blob/master/lib/mask_text_input_formatter.dart#L133). You have to do this manually. – om-ha Feb 25 '20 at 12:48

1 Answers1

3

Solution

For your specific use case, here's a solution you can try:

TextField(
    inputFormatters: [
        WhitelistingTextInputFormatter(RegExp(r"^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]|(?:Jan|Mar|May|Jul|Aug|Oct|Dec)))\1|(?:(?:29|30)(\/|-|\.)(?:0?[1,3-9]|1[0-2]|(?:Jan|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec))\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)(?:0?2|(?:Feb))\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9]|(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep))|(?:1[0-2]|(?:Oct|Nov|Dec)))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$")),
    ],
);

Explanation

You can't validate the text like you want with mask_text_input_formatter pub as it performs comparison char by char. So you can only validate each individual char using regex.

To perform manual validation of the text of TextField or TextFormField`, then you need to use TextInputFormatter. More specifically using either BlacklistingTextInputFormatter or WhitelistingTextInputFormatter. For another example different from your question, here's How to restrict two dots.

Regex expression is taken from this answer, test cases for this particular regex can be found here.

Automatically inserting hyphens

If you want to automatically insert hyphens then you'll need to work within onChanged. Here's a simple example for doing this.

If you're going for this approach, you can validate the text within onChanged but you'll also have to reset the recently-changed invalid text with valid one since onChanged is called AFTER the text has already been changed. So this is lazy validation unlike BlacklistingTextInputFormatter or WhitelistingTextInputFormatter which offer eager validation before the text is even modified.

om-ha
  • 1,441
  • 9
  • 20