The secret to async validation on Flutter forms

In forms it is often useful to look-up something using a backend service to validate a field. A common example is validating a username and password on a database.

The Situation

You might think that the Flutter team would decide to support this out of the box. Unfortunately they do not, and they don’t plan to either. However, there is a good reason why not. Flutter support for async form validation can lead to bad UI ( because developers can combine use of sync and async validators inappropriately and bugs can be hard to find).

So, without official Flutter support for async validators, how is it possible to get a nice clean form interface using the built-in (sync only) validators and still be able to make async calls to validate form fields?

There is a solution. It is possible to emulate async validator behavior.

The Secret

The secret can be broken into three parts

  1. First setup a local boolean that maintains the success/failure of the result of the async call. Then add this to the sync validator to generate an async validation message that describes the failure case (like ‘Invalid Username’).
  2. After submitting a form and passing the sync validator make an async call (like to a backend). After returning from the async call, set the local boolean with the success/failure of the result of the async call and call SetState(). This will redraw the form…. But it will not re-rerun the async validator!
    There is a solution for that too!
  3. Place a call to explicitly re-run the async validator at the start of the build() method. This will re-run the async validator before the form is rebuilt. After the form completes rebuilding, the async validator results are displayed (if any) on the form just like you would expect.

Let’s see it!

Here is a demo of this in action:

There’s a lot going on in this screen, so I’ll break it down:

  1. The user first enters a username and password that triggers the sync validator and displays an error message (must be 8 characters). This is the normal use of a form validator.
  2. The user then enters a username and password that passes the sync validator. This is where the secret sauce kicks in. Once the sync validator passes, a call is made to the backend. The result from the backend indicates the username/password combination are incorrect, so the async validator is triggered and displays an error message(incorrect user/pass).
  3. The user then enters the correct user/pass combination. This initiates another call to the backend. This time the user/pass is correct and no validators (sync or async) are triggered. The user is then logged in.

Show me how

You can find the source code here, which also includes a package for managing the progress indicator during the async call:

Finally…

Let me know if you have any questions or comments about this method of async form validation for Flutter, below or on GitHub or Twitter.

If you think this article is useful, it helps if you clap, like, subscribe and share with your friends for more Flutter developer articles.