Flutter

Flutter Form Validation

As a developer, I can understand that whenever we create a form, how important it is to validate it. Form validation is a technical process where a form check  if the information provided by a user is correct. whether it is client side or server side. The main goal of form validation is to ensure that the user provided necessary and properly formatted information needed to successfully complete an operation.

For example, email-checker won’t let me use an email address that is incorrectly formatted, and gives me an error message when I try to do so:

And when I correctly enter email address, it works, and the error message disappears:

In this article, we are going to learn how we can validate the form in Flutter. It is very easy to validate any form in Flutter, by following some steps, you can validate any Flutter form.

Directory Structure

Step 1: create a form

This is a basic form with three input fields , there is a update password button with old Password, new Password and conform password Here all the three fields are required that means there should be no empty . This is the form which is the change password form, Well, whatever it is, we have to learn validation, which you can use in any form.

So in main.dart i have created the form.

import 'package:flutter/material.dart';

import 'form_error.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Form validation',
      theme: ThemeData(
       primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Form Validation'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.teal,
          title: Text(widget.title),
      ),
      body: SingleChildScrollView(
        child: Form(
          key: _formKey,
          child: Column(
            children: [
              Container(
                margin: EdgeInsets.all(10),
                child: Center(
                  child: Text("Change My Password" ,style: TextStyle(fontWeight: FontWeight.bold,color: Colors.black87,fontSize: 18),),
                ),
              ),
              Divider(),
              Container(
                margin: EdgeInsets.all(10),
                child: TextFormField(
                       decoration: InputDecoration(
                      labelText: "Old Password",
                      labelStyle: TextStyle(
                        fontWeight: FontWeight.bold,
                        fontSize: 15,
                        color: Colors.teal,
                      )
                  ),
                  style: TextStyle(
                    fontWeight: FontWeight.bold,
                    fontSize: 15,
                  ),
                ),
              ),
              Container(
                margin: EdgeInsets.all(10),
                child: TextFormField(
                      decoration: InputDecoration(
                      labelText: "New Password",
                      labelStyle: TextStyle(
                        fontWeight: FontWeight.bold,
                        fontSize: 15,
                        color: Colors.teal,
                      )
                  ),
                  style: TextStyle(
                    fontWeight: FontWeight.bold,
                    fontSize: 15,
                  ),
                ),
              ),
              Container(
                margin: EdgeInsets.all(10),
                child: TextFormField(
                      decoration: InputDecoration(
                      labelText: "Conform Password",
                      labelStyle: TextStyle(
                        fontWeight: FontWeight.bold,
                        fontSize: 15,
                        color: Colors.teal,
                      )
                  ),
                  style: TextStyle(
                    fontWeight: FontWeight.bold,
                    fontSize: 15,
                  ),
                ),
              ),
              FormError(errors: errors,key: ValueKey("error"),),
              Container(
                margin: EdgeInsets.all(10),
                child: RaisedButton.icon(
                    color: Colors.teal,
                    onPressed: (){
                     
                    },
                    icon: Icon(
                      Icons.change_circle,
                      color: Colors.white,
                    ),
                    label: Text("Change Password",
                      style: TextStyle(
                          color: Colors.white,
                          fontWeight: FontWeight.bold
                      ),
                    )
                ),

              )

            ],
          ),
        ),
      ),

    );
  }
}

Now we have to validate this form, then we have to wrap the column widget with the form widget. the Form widget acts as a container for grouping and validating multiple form fields. And also have to GlobalKey ,this uniquely identifies the Form

import 'package:flutter/material.dart';

// Define a custom Form widget.
class MyForm extends StatefulWidget {
  const MyForm({Key? key}) : super(key: key);

  @override
  MyFormState createState() {
    return MyFormState();
  }
}

// Define a corresponding State class.
// This class holds data related to the form.
class MyFormState extends State<MyForm> {
  // Create a global key that uniquely identifies the Form widget and allows validation of the form.
  //
  // Note: This is a `GlobalKey<FormState>`,
  // not a GlobalKey<MyFormState>.
  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    // Build a Form widget using the _formKey created above.
    return Form(
      key: _formKey,
      child: Column(
        children: <Widget>[
          // Add TextFormFields and ElevatedButton here.
        ],
      ),
    );
  }
}
 Note: This is a `GlobalKey<FormState>`,
   not a GlobalKey<MyCustomFormState>.

Step 2 : TextFormField with validation 

Now we are creating a validator that ensures the TextFormField isn’t empty. f it is empty, return a friendly error message whatever you want to give.

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;
  },
),

Step 3: Submit the form

After applying validator in TextFormField we will create submit button user can tap to submit the information. Whenever user attempts to submit check if the form is valid if it is display a submit message if isn’t disaplay the error message

RaisedButton.icon(
                    color: Colors.teal,
                    onPressed: (){
                      if (_formKey.currentState!.validate()) {
                      _formKey.currentState!.save();
                        ScaffoldMessenger.of(context).showSnackBar(
                             const SnackBar(content: Text('Processing Data')),
                        );
                      }
                    },
                    icon: Icon(
                      Icons.change_circle,
                      color: Colors.white,
                    ),
                    label: Text("Change Password",
                      style: TextStyle(
                          color: Colors.white,
                          fontWeight: FontWeight.bold
                      ),
                    )
                ),

Now we have started getting error messages and success messages. but to make the error message friendly, we create a new dart file.

form_error.dart

import 'package:flutter/material.dart';

class FormError extends StatelessWidget {
  const FormError({
    required Key key,
    required this.errors,
  }) : super(key: key);

  final List<String> errors;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: List.generate(
          errors.length, (index) => formErrorText(error: errors[index])),
    );
  }

  Row formErrorText({required String error}) {
    return Row(
      children: [
        Icon(Icons.error),
        SizedBox(
          width:10,
        ),
        Text(error),
      ],
    );
  }
}

call this file me main.dart like this :

 FormError(errors: errors,key: ValueKey("error"),),

Full Main.dart

import 'package:flutter/material.dart';

import 'form_error.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Form validation',
      theme: ThemeData(
       primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Form Validation'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final _formKey = GlobalKey<FormState>();
  late String conform_password;
  late String new_password;
  late String old_password;

  final List<String> errors = [];

  void addError({required String error}) {
    if (!errors.contains(error))
      setState(() {
        errors.add(error);
      });
  }

  void removeError({required String error}) {
    if (errors.contains(error))
      setState(() {
        errors.remove(error);
      });
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.teal,
          title: Text(widget.title),
      ),
      body: SingleChildScrollView(
        child: Form(
          key: _formKey,
          child: Column(
            children: [
              Container(
                margin: EdgeInsets.all(10),
                child: Center(
                  child: Text("Change My Password" ,style: TextStyle(fontWeight: FontWeight.bold,color: Colors.black87,fontSize: 18),),
                ),
              ),
              Divider(),
              Container(
                margin: EdgeInsets.all(10),
                child: TextFormField(
                  onSaved: (newValue) => old_password = newValue!,
                  validator: (value) {
                    if (value!.isEmpty) {
                      addError(error: "Please Add old password");
                      return "";
                    }
                    if (value.isNotEmpty) {
                      removeError(error: "Please Add old password");
                      // return "";
                    }

                    return null;
                  },
                  // controller: oldpwdController,
                  decoration: InputDecoration(
                      labelText: "Old Password",
                      labelStyle: TextStyle(
                        fontWeight: FontWeight.bold,
                        fontSize: 15,
                        color: Colors.teal,
                      )
                  ),
                  style: TextStyle(
                    fontWeight: FontWeight.bold,
                    fontSize: 15,
                  ),
                ),
              ),
              Container(
                margin: EdgeInsets.all(10),
                child: TextFormField(
                  onSaved: (newValue) => new_password = newValue!,
                  validator: (value) {
                    if (value!.isEmpty) {
                      addError(error: "Please Add new password");
                      return "";
                    }
                    if (value.isNotEmpty) {
                      removeError(error: "Please Add new password");
                      // return "";
                    }

                    return null;
                  },
                  // controller: newpwdController,
                  decoration: InputDecoration(
                      labelText: "New Password",
                      labelStyle: TextStyle(
                        fontWeight: FontWeight.bold,
                        fontSize: 15,
                        color: Colors.teal,
                      )
                  ),
                  style: TextStyle(
                    fontWeight: FontWeight.bold,
                    fontSize: 15,
                  ),
                ),
              ),
              Container(
                margin: EdgeInsets.all(10),
                child: TextFormField(
                  onSaved: (newValue) => conform_password = newValue!,
                  validator: (value) {
                    if (value!.isEmpty) {
                      addError(error: "Please Add conform password");
                      return "";
                    }
                    if (value.isNotEmpty) {
                      removeError(error: "Please Add conform password");
                      // return "";
                    }


                        return null;
                  },
                  // controller: confirmpwdController,
                  decoration: InputDecoration(
                      labelText: "Conform Password",
                      labelStyle: TextStyle(
                        fontWeight: FontWeight.bold,
                        fontSize: 15,
                        color: Colors.teal,
                      )
                  ),
                  style: TextStyle(
                    fontWeight: FontWeight.bold,
                    fontSize: 15,
                  ),
                ),
              ),
              FormError(errors: errors,key: ValueKey("error"),),
              Container(
                margin: EdgeInsets.all(10),
                child: RaisedButton.icon(
                    color: Colors.teal,
                    onPressed: (){
                      if (_formKey.currentState!.validate()) {
                      _formKey.currentState!.save();
                      print("conform_password $conform_password");
                      print("new_password $new_password");
                      print("old_password $old_password");
                      }
                    },
                    icon: Icon(
                      Icons.change_circle,
                      color: Colors.white,
                    ),
                    label: Text("Change Password",
                      style: TextStyle(
                          color: Colors.white,
                          fontWeight: FontWeight.bold
                      ),
                    )
                ),

              )

            ],
          ),
        ),
      ),

    );
  }
}

OUTPUT

RECOMMENDED ARTICLES





Leave a Reply

Your email address will not be published. Required fields are marked *