1 of 32

1

Chong Yong Shean

Google Developer Expert - Flutter,

Senior Software Engineer @ Comerge Solutions

Elegant Form Validation in Flutter

2 of 32

2

Agenda

  1. Importance of form validation
  2. Basic validation techniques
  3. Control when to validate
  4. Deep dive into TextFormField
  5. Handling complex validation scenarios
  6. When to use TextField?

3 of 32

3

Why form validation?

  • Ensure user input meets requirements
  • Prevent failures due to incorrect or incomplete data
  • Provide immediate feedback and improve UX
  • Protect system from malicious attacks

4 of 32

4

Our task today

✅ Ensure user input meets requirements

✅ Show error message below field if not

✅ Only submit form when the form is valid

✅ Show server validation error below field

5 of 32

5

A simple poll + Q&A

Join at

slido.com

#1469 130

6 of 32

6

Basic validation techniques

7 of 32

7

Flutter Form, TextField, TextFormField

Form - for grouping & validating multiple form fields

TextField - for entering text

TextFormField - TextField with validation

slido.com #1469 130

8 of 32

8

Built-in validation methods

Create a Form to contain the TextFormFields and submit button

final _formKey = GlobalKey<FormState>();

Form(

key: _formKey,

child: Column(

children: [...],

),

),

slido.com #1469 130

9 of 32

9

Built-in validation methods

TextFormField’s validator

TextFormField(

// The validator receives the text that the user has entered

validator: (value) {

if (value == null || value.isEmpty) {

return 'Please enter some text';

}

return null;

},

),

slido.com #1469 130

10 of 32

10

Built-in validation methods

Call _formKey.currentState!.validate() to trigger validation

ElevatedButton(

onPressed: () {

// Validate returns true if the form is valid, or false otherwise.

if (_formKey.currentState!.validate()) {

// If the form is valid, display a snackbar.

ScaffoldMessenger.of(context).showSnackBar(

const SnackBar(content: Text('Processing Data')),

);

}

},

child: const Text('Submit'),

),

slido.com #1469 130

11 of 32

11

Result

slido.com #1469 130

12 of 32

12

Control when to validate

13 of 32

13

Validation on submit

Triggers validation whenever the form is submitted.

✅ Done in the previous example

ElevatedButton(

onPressed: () {

// Validate returns true if the form is valid

if (_formKey.currentState!.validate()) {

// If the form is valid, display a snackbar.

ScaffoldMessenger.of(context).showSnackBar(

const SnackBar(content: Text('Processing Data')),

);

}

},

child: const Text('Submit'),

),

14 of 32

14

Validation on mount/render

Triggers validation whenever the form is mounted, regardless if the form/field has been changed.

Use AutovalidateMode.always in Form or TextFormField:

Form(

autovalidateMode: AutovalidateMode.always,

child: Column(

children: [

TextFormField(

autovalidateMode: AutovalidateMode.always,

),

],

),

),

15 of 32

15

Validation on change

Triggers validation when any field of the form (or a specific field) has been changed, use AutovalidateMode.onUserInteraction

Form(

autovalidateMode: AutovalidateMode.onUserInteraction,

child: Column(

children: [

TextFormField(

autovalidateMode: AutovalidateMode.onUserInteraction,

),

],

),

),

16 of 32

16

Disable validation

If you want to skip validation, use AutovalidateMode.disabled

Form(

autovalidateMode: AutovalidateMode.disabled,

child: Column(

children: [

TextFormField(

autovalidateMode: AutovalidateMode.disabled,

),

],

),

),

17 of 32

17

Deep Dive into TextFormField

18 of 32

18

TextFormField

decoration: <InputDecoration>

TextFormField(

// decoration is everything you need to “decorate” the field, controls the UI

decoration: InputDecoration(

labelText: 'Password',

suffixIcon: IconButton(...),

filled: true,

fillColor: Colors.black12,

border: OutlineInputBorder(

borderRadius: BorderRadius.circular(10),

),

focusedBorder: ...,

errorStyle: const TextStyle(...),

),

19 of 32

19

TextFormField

textInputAction

TextInputAction.next

To move the cursor to the next field

TextInputAction.done

To close the keyboard

20 of 32

20

TextFormField

onChanged: Triggered whenever the field value has changed

TextFormField(

onChanged: (value) {

// you can obtain the current value from here

setState(() => username = value);

// or reset the async validation error state

setIsUsernameAlreadyTaken(false);

},

),

21 of 32

21

TextFormField

onSaved: Triggered whenever formKey.currentState.save() is called

TextFormField(

onSaved: (value) {

// save the validated value to the state

setState(() => username = value);

},

),

22 of 32

22

Handling complex validation scenarios

23 of 32

23

github.com/yshean/form_validation_demo

Use for a URL or a CTA

24 of 32

24

When to use TextField?

25 of 32

25

You don’t want to nest it under Form.

If you only have one field, or you don’t need the validation, then TextField is 👍.

26 of 32

26

You want to manage validations on your own.

If you like to keep your view clean and delegate every form logic to a controller or bloc, then TextField is 👍.

27 of 32

27

But… everything is more verbose (harder 😓) with TextField

TextField does not include validation.

We need to DIY validation by defining onChanged, focusNode, controller, etc.

28 of 32

28

General idea of how to do validation with TextField

  • Obtain the value from TextField (either via onChanged or controller.value)
  • Pass the value through your validator which outputs the validation error
  • Display the validation error in a text widget (possibly below the TextField)

29 of 32

29

Example: Validation on blur (with TextField)

Triggers validation when a field is unfocused

We need FocusNode:

  • Instantiate a FocusNode in the Form
  • Attach the FocusNode to the TextField
  • Add a listener to the FocusNode
  • Clean up the FocusNode on dispose

30 of 32

30

Key takeaways

31 of 32

31

Key takeaways

✅ Use Form & TextFormField whenever you can

✅ Use TextField only for very simple cases

✅ Use InputDecoration for customising text editing area

✅ Combine TextFormFields validator with local states for a non-Material/Cupertino look

32 of 32

32

linkedin.com/in/yshean

Comerge Solutions is hiring! We are an international team based in Zürich and Kuala Lumpur who are proud to produce software you like.

Talk to me for more info:)

https://github.com/yshean/form_validation_demo