Flutter: Scrolling to the first invalid form field

ยท

3 min read

Flutter: Scrolling to the first invalid form field

Do you want functionality like scrolling to the first invalid field (after being validated)?

So, one of my projects has verrry long form fields. (I know it's imperfect at UX, but that is the specifics of the application). And that came to the question I mentioned above. But the problem is that I don't want to maintain many keys for all form fields.

You might say: "You can make a copy of the form.dart file and modify it.". But how about the other packages whose widgets extend FormField class, like date_field, flutter_typeahead, ... I don't want to continue copying its.

Some other packages like flutter_form_builder, ready_form, also provided ability to automatically scroll to first error when form validation fails. But my project has come to an end. I don't want to change a lot.

Deep in the form.dart file, I came to the idea of the dart mixin (it can add features to a class) and registering all the form fields by myself.

By creating a mixin and restricting the type on FormFieldState<T>, I can override and interfere with the validation process to update the error and scroll to that field if it is invalid.

  @override
  bool validate() {
    final bool result = super.validate();

    // update error text

    return result;
  }

  @override
  Widget build(BuildContext context) {
    final result = super.build(context);

   // update error text

    return result;
  }

This is fitting for my project too. Since I prefer to customize all the form fields by myself. Even with the TextField.

Thought that was enough, but I came back to the question about the other packages (which widgets extend FormField class). We only can determine whether FormField has been invalidated by accessing the GlobalKey<FormFieldState>. Well, we can accept that problem and maintain the key by ourselves, since each screen might have a few widgets that came from the package.

In the future, there might be some improvements to Form API. Did you interest in this topic? Or have a need for this? So, make sure you give a ๐Ÿ‘ to the issue #67283.


Did you think this article is ending and have a little bit of disappointment ๐Ÿ˜ž. Well, I am completing this article ๐Ÿ˜



by saying that "I'm can't accept that problem!". There will be some workaround to solve that.

I thought if I created a GlobalKey in StatefulWidget, and passed that key to the builder function, I can access FormFieldState with some limit. Also, we have a problem with the validator too. With mixin, I can (just to remind you) interfere with the validation process to update the error and scroll to that field if it is invalid. There is only one way I can think. That is to declare the validator in the StatefulWidget, modify it and pass it to the builder function (again).

The builder function now looks like this:

  final Widget Function(
    GlobalKey<FormFieldState<T>> formFieldKey,
    FormFieldValidator<T> validator,
  ) builder;

I named this StatefulWidget is FormFieldRegisteredWidget, and here is an example with package date_field.

FormFieldRegisteredWidget(
  validator: (DateTime? value) {
    if (value == null) {
      return "Empty!";
    }

    return null;
  },
  builder: (
    GlobalKey<FormFieldState<DateTime>> formFieldKey,
    String? Function(DateTime?) validator,
  ) {
    return DateTimeFormField(
      key: formFieldKey,
      validator: validator,
      onDateSelected: (value) {
        // perform setState
      },
      mode: DateTimeFieldPickerMode.date,
      initialValue: selectedDate,
    );
  },
),

I think it has a bit of verbose, but I accept that.

For now, you might think I will show the package that I published on pub.dev.



Well, I did not publish it yet! ๐Ÿ˜• Should I?

But, I do publish it on Github. ๐Ÿ˜ƒ

You can try it by adding this as a dependency in the pubspec.yaml file:

  flutter_form_registry:
      git:
        url: https://github.com/thanhle1547/flutter_form_registry

Let me know what you think in the comment section. I always welcome any feature requests.

I hope I added some value to the time you invested.

If you find the article interesting, please hit the reactions.