form_bloc icon indicating copy to clipboard operation
form_bloc copied to clipboard

inputFormatters not working correctly

Open wizawuza opened this issue 4 years ago • 3 comments

OS: Android Version: flutter_form_bloc: ^0.14.0 Flutter Version: 1.17.2

When trying to use inputFormatters, whitelisting does not work immediately, and creates an incorrect response.

For example:

TextFieldBlocBuilder(
  textFieldBloc: formBloc.productAmount,
  keyboardType: TextInputType.number,
  inputFormatters: [
    WhitelistingTextInputFormatter(RegExp(r'[0-9]')),
  ],
),

That should allow only numbers, correct?

When I type "123", it works. Then I add a decimal ".". The field now has "123." I hit decimal one more time, and ".123." is now in the field, likely due to the value being updated without proper cursor resetting.

When I do it with a vanilla TextFormField:

TextFormField(
  keyboardType: TextInputType.number,
  inputFormatters: [
    WhitelistingTextInputFormatter(RegExp(r'[0-9]')),
  ],
),

It works as you would expect.. entering anything other than a digit is ignored.

wizawuza avatar May 30 '20 21:05 wizawuza

The offending code seems to be: https://github.com/GiancarloCode/form_bloc/blob/947f19b516c074dab28fe62bc6d08a0ac5b0da63/packages/flutter_form_bloc/lib/src/text_field_bloc_builder.dart#L857

The onChanged updates the bloc's value regardless of whether or not the inputFormatter tries to cancel the new character:

onChanged: (value) {
  widget.textFieldBloc.updateValue(value);
  if (widget.onChanged != null) {
    widget.onChanged(value);
  }
},

wizawuza avatar May 30 '20 22:05 wizawuza

I've changed the function to be like this instead:

onChanged: (value) {
  if(widget.preCheck == null) {
    widget.textFieldBloc.updateValue(value);
  } else {
    if(widget.preCheck(value)) {
      widget.textFieldBloc.updateValue(value);
    } else {
      widget.textFieldBloc.updateValue(widget.textFieldBloc.value);
      _controller.value = TextEditingValue(
        text: widget.textFieldBloc.value,
        selection: TextSelection(baseOffset: widget.textFieldBloc.value.length, extentOffset: widget.textFieldBloc.value.length),
      );
    }
  }
  if (widget.onChanged != null) {
    widget.onChanged(value);
  }
},

Where preCheck is an optional function that's passed in that returns true if it's valid code, false otherwise.

If you agree with this implementation please let me know and either implement or tell me to do a PR.

Thank you.

PS: I noticed you have a TODO in that file // TODO: Find out why the cursor returns to the beginning., my code above for _controller.value might be helpful.

wizawuza avatar May 31 '20 12:05 wizawuza

any news ?

devZakariya avatar Jul 04 '20 13:07 devZakariya