Flutter Tutorial #1 — Form Validation.

Flutter Tutorial #1 — Form Validation.

Hello everyone and welcome to another brand new tutorial series on Flutter. Today we’re going to learn how to validate a form using Flutter.

Image for post

Form plays a vital role in any mobile application today. Almost all the app in the world has a form to fill.

Overview of this tutorial. This app will have 5 text fields consisting of :

  • Full name
  • Email address
  • Phone number
  • Password
  • Confirm Password

and a submit button for validation. If the user inputs are invalid according to the rules we set, we would simply display a snack bar that contains the error message e.g Invalid email address as shown below.

Image for post

Let dive into coding now!!!

Creating our UI(user interface).

Create a new flutter project and clear out all generated code in the main.dart file. First, import the material package

import 'package:flutter/material.dart';

Then define the main function like this with a Stateless widget called MyApp:

void main() {
   runApp(MyApp());
}
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
       title: 'Flutter Beginner Tutorial',
       theme: ThemeData(
         primarySwatch: Colors.green,
         visualDensity: VisualDensity.adaptivePlatformDensity,
       ),
       home: MyHomePage(),
    );
  }
}

Creating a StatefulWidget for MyHomePage(), it should look like this:

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

So, under _MyHomePageState extends State we’re going to declare a controller for each of our form fields:

TextEditingController _name = TextEditingController();
TextEditingController _email = TextEditingController();
TextEditingController _phn = TextEditingController();
TextEditingController _pass = TextEditingController();
TextEditingController _cpass = TextEditingController();
// we declare a _ScaffoldState here called _formKey because we're going to change the state of the app by showing the snack bar
var _formKey = GlobalKey<ScaffoldState>();
bool hidePass = true; // this is probably for showing and hiding our password

In the build widget instead of returning a Container widget, we’re going to return a Scaffold() widget, full code:

Scaffold(
      key: _formKey,
      appBar: AppBar(
        title: Text('Simple Form Validation'),
        centerTitle: true,
        elevation: 0,
      ),
      body: Center(
        child: SingleChildScrollView(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Center(
                child: Text(
                  'Register Page',
                  style: TextStyle(
                    fontSize: 24,
                    fontWeight: FontWeight.w300,
                  ),
                ),
              ),
              Padding(
                padding: EdgeInsets.all(20),
                child: Column(
                  children: <Widget>[
                    TextFormField(
                      controller: _name, // the controller we declared at the top
                      decoration: InputDecoration(
                        icon: Icon(Icons.person),
                        labelText: 'Full Name',
                      ),
                    ),
                    SizedBox(height: 10),
                    TextFormField(
                      controller: _email, // the controller we declared at the top
                      decoration: InputDecoration(
                        labelText: 'Email Address',
                        icon: Icon(Icons.mail),
                      ),
                    ),
                    SizedBox(height: 10),
                    TextFormField(
                      controller: _phn, // the controller we declared at the top
                      keyboardType: TextInputType.number,
                      decoration: InputDecoration(
                        labelText: 'Phone Number',
                        icon: Icon(Icons.call),
                      ),
                    ),
                    SizedBox(height: 10),
                    TextFormField(
                      controller: _pass,
                      obscureText: hidePass, // the bool we declared earlier 
                      decoration: InputDecoration(
                        labelText: 'Password',
                        icon: Icon(Icons.security),
                        suffixIcon: IconButton(
                          icon: Icon(Icons.visibility),
                          onPressed: () {
                            showandhide(); // we are going to declare a function for showing the password inout call showandhide()
                          },
                        ),
                      ),
                    ),
                    SizedBox(height: 10),
                    TextFormField(
                      obscureText: hidePass,
                      controller: _cpass,
                      decoration: InputDecoration(
                        labelText: 'Confirm Password',
                        icon: Icon(Icons.border_color),
                        suffixIcon: IconButton(
                          icon: Icon(Icons.visibility),
                          onPressed: () {
                            showandhide();
                          },
                        ),
                      ),
                    ),
                    SizedBox(height: 15),
                    SizedBox(
                      width: 300,
                      child: MaterialButton(
                        onPressed: () {
                          formValidate(
                            name: _name.text,
                            email: _email.text,
                            cpass: _cpass.text,
                            pass: _pass.text,
                            phn: _phn.text,
                          ); // formValidate consist of all of our inputs, so we're just going to declare a function to check they all if the user input is valid or otherwise.
                        },
                        child: Text(
                          'Submit Form',
                          style: TextStyle(color: Colors.white),
                        ),
                        color: Colors.green,
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );

So, we have to collect all our user input and set it inside initState and dispose of it as well.

@override
  void initState() {
    _name = TextEditingController();
    _email = TextEditingController();
    _phn = TextEditingController();
    _pass = TextEditingController();
    _cpass = TextEditingController();
    super.initState();
  }
  @override
  void dispose() {
    _name.dispose();
    _email.dispose();
    _phn.dispose();
    _pass.dispose();
    _cpass.dispose();
    super.dispose();
  }

Show and hide user password:

showandhide() {
    setState(() {
      hidePass = !hidePass; 
//this just means if the eye icon is pressed hidepass is not equal to hidepass so true != true i.e false
    });
  }

So after all this, we have now got to the form validation itself:

// here we collect every information we need concerning the input
formValidate({String name, email, phn, pass, cpass}) {
    if (name.toString().isEmpty) {
      _showInSnackBar(message: 'Full name required');
    } else if (!email.toString().contains('@')) {
      _showInSnackBar(message: 'Invalid email address');
    } else if (phn.toString().isEmpty || phn.length != 11) {
      _showInSnackBar(message: 'Invalid phone number');
    } else if (pass.toString().isEmpty || pass.length != 8) {
      _showInSnackBar(message: '8 character required for password');
    } else if (cpass.toString() != pass.toString()) {
      _showInSnackBar(message: 'Password does not match');
    } else {
      openDia(name: name); 
//so after all the input is valid we want to display a little dialog.
    }
  }

Our snack bar code:

void _showInSnackBar({String message}) {
    _formKey.currentState.showSnackBar(
      SnackBar(
        content: GestureDetector(
          onTap: () {},
          child: Text(
            message,
            style: TextStyle(color: Colors.white, fontWeight: FontWeight.w600),
          ),
        ),
        duration: (Duration(seconds: 4)),
        elevation: 0,
        backgroundColor: Colors.black,
      ),
    );
  }

and the Dialog code as well:

openDia({String name}) {
    showDialog(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            content: Text('$name is now a verified account'),
            title: Text('Registration Successful'),
            actions: <Widget>[
              MaterialButton(
                onPressed: () {
                  Navigator.pop(context);
                },
                child: Text(
                  'Verified',
                  style: TextStyle(color: Colors.blue),
                ),
              )
            ],
          );
        });
  }

If we run our app now we should have something similar to this

Image for post

Complete source code do well by staring ⭐ the repo:

Congrats, you have finally learned how to validate user input and also learned how to improve user experience by showing a beautiful error message.

If you enjoyed this article as much as I did you can support me by 👏 for this story and leave a comment below if you have any questions. Thanks

🔗 Social Media / Let's Connect 🔗 ==> Github | Twitter | Youtube | WhatsApp | LinkedIn | Patreon | Facebook.

Join the Flutter Dev Community 👨‍💻👨‍💻 ==> Facebook | Telegram | WhatsApp | Signal.

Subscribe to my Telegram channel | Youtube channel | and also to hashnode newsletter in the input box above 👆👆. Thanks

Happy Fluttering 🥰👨‍💻