Home > Net >  Don't allow consecutive same character and some different character together in TextFormField
Don't allow consecutive same character and some different character together in TextFormField

Time:10-05

I want to restrict the TextFormField to only accept numbers separated by commas and sometimes with dashes but I don't want them to come consecutive to each other and also don't want the same character consecutive.

Ex:-

  • 1,3-4,9-11 is correct
  • 1,,3--4,9-11 is wrong
  • 1,-3-4,9-11 is wrong
  • 1-,3-4,9-11 is wrong

To restrict things to only numbers, commas and dashes I'm using:-

FilteringTextInputFormatter(
   RegExp("[0-9,-]"),
   allow: true
)

But it is not restricting the consecutive behavior as shown in the wrong behavior in the examples.

So, how can I restrict my TextFormField to the correct behavior represented in the examples?

Thank you.

Update: I finally followed this approach for this problem.

CodePudding user response:

If you want to validate on submit, you might write the pattern as:

^[0-9] (?:[,-][0-9] )*$

Regex demo

If a negative lookahead is supported, you an exclude matching 2 times one of - or , while validating on typing.

Note that this will allow , or - at the end:

^(?!.*[,-][,-])[0-9,-]*

Regex demo

CodePudding user response:

For my problem above I finally combined FilteringTextInputFormatter with a custom TextInputFormatter specific to my case so I'm adding it below so that if anyone wants to do the same they can have a look at this approach:

class RangeTextInputFormatter extends TextInputFormatter {
  @override
  TextEditingValue formatEditUpdate(
    TextEditingValue oldValue,
    TextEditingValue newValue,
  ) {
    TextSelection newSelection = newValue.selection;
    String truncated = newValue.text;

    int oldValueLength = oldValue.text.length;
    int newValueLength = newValue.text.length;

    // Blocks comma and dash at start.
    if ((oldValue.text.isEmpty || oldValue.text == "") &&
        (newValue.text[newValueLength - 1] == "," ||
            newValue.text[newValueLength - 1] == "-")) {
      truncated = oldValue.text;
      newSelection = oldValue.selection;
    }
    // Allows numbers at start.
    else if (oldValue.text.isEmpty || oldValue.text == "") {
      truncated = newValue.text;
      newSelection = newValue.selection;
    } else {
      // Blocks comma and dash after comma.
      if (oldValue.text[oldValueLength - 1] == "," &&
          (newValue.text[newValueLength - 1] == "," ||
              newValue.text[newValueLength - 1] == "-")) {
        truncated = oldValue.text;
        newSelection = oldValue.selection;
      }
      // Blocks comma and dash after dash.
      else if (oldValue.text[oldValueLength - 1] == "-" &&
          (newValue.text[newValueLength - 1] == "," ||
              newValue.text[newValueLength - 1] == "-")) {
        truncated = oldValue.text;
        newSelection = oldValue.selection;
      }
      // Blocks dash after number dash number. Ex: 48-58- <- this last dash is blocked
      else if (oldValue.text.lastIndexOf('-') != -1) {
        if (!(oldValue.text
                .substring(oldValue.text.lastIndexOf('-'))
                .contains(",")) &&
            newValue.text[newValueLength - 1] == "-") {
          truncated = oldValue.text;
          newSelection = oldValue.selection;
        }
      }
    }

    return TextEditingValue(
      text: truncated,
      selection: newSelection,
      composing: TextRange.empty,
    );
  }
}

Now use it just like FilteringTextInputFormatter:

inputFormatters: [
      FilteringTextInputFormatter(RegExp("[0-9,-]"), allow: true),
      RangeTextInputFormatter(),
]
  • Related