flutter

how to use forms in flutter easy tutorial

In this brief explanation i want to show you in the most easy way possible how you can create a form and how it works.

Why we should use forms

Forms are an easy way to manipulate multiple inputs, they make our live so easy that we can use one instruction to check that all our inputs are valid or one instruction to save our data.

But how forms work?

Before we start to press keys without knowing how things works we must know ho forms works and what are the benefits using them.

To make thing easy i will use only 2 features of forms, the validate and the save methods.

The validate method it'll call all the validator functions inside each input validating our inputs, if returns null it'll continue but if returns a string that means that will display that string as an error message, this help us to automate the validation process.

The save method in the other hand will call all the onSaved functions inside each field to perform the save process that we will define; It works similar to the validate method.

Obviously all your input fields must be inside the form widget!

Here a simple image that summarize what i have said :D

Inputs are connected with the validate and save method

Creating our form

To begin our adventure we first have to use the form widget and put inside it all our inputs.

The form needs a GlobalKey, we use global keys so we can identify our lovely form.

Until now you will have something like this...

Dart
import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      home: Scaffold(
        body: MyForm(),
      ),
    )
  );
}

class MyForm extends StatefulWidget {
    
  
  _MyFormState createState() => _MyFormState();
  
}

class _MyFormState extends State<MyForm> {
    
  final _keyForm = GlobalKey<FormState>(); // Our created key

  
  Widget build(BuildContext context) {
    
    // The form widget
    return Form(
      key: _keyForm,
      
    );
    
  }
  
}

Now it's time to create the fields that we want to add to our form... let's suppose that we want 3 fields to make it simple!

  • name
  • password
  • email

To add these field we will use a simple widgets that will provide us with the basic graphics of the material design, this widget is called TextFormField.

The field that will contain our password will have an extra property "obscureText" to show the black dotted chars instead of the actual visible password. 😉️

Only for style purpose we add a hint text so the user knows what to insert in that field 😁️

Dart
class _MyFormState extends State<MyForm> {

  final _keyForm = GlobalKey<FormState>();
  final _name = TextEditingController();
  final _password = TextEditingController();
  final _email = TextEditingController();

  
  Widget build(BuildContext context) {

    return Form(
      key: _keyForm,
      child: Padding(
        padding: const EdgeInsets.all(20),
        child: ListView(
          children: [
            Container(
              padding: const EdgeInsets.symmetric(vertical: 20),
              child: Text('Some inputs...'),
            ),            
            TextFormField(
              controller: _name,
              decoration: InputDecoration(hintText: 'Insert your name.'),
            ),
            TextFormField(
              controller: _password,
              obscureText: true,
              decoration: InputDecoration(hintText: 'The password to log in.'),
            ),
            TextFormField(
              controller: _email,
              decoration: InputDecoration(hintText: 'E-mail to use for log in.'),
            ),
          ],
        ),
      ),
    );

  }
}

Creating a simple User class 

We will create a simple user class only for the purpose to show how we can save our user his properties are not final... 😵️

Dart
class User {
  String name;
  String password;
  String email;

  User({ this.name, this.password, this.email });
}

Validate and save methods

Before validating or saving our fields we must add 2 parameters to all our TextFormFields a validator and onSaved.

Now it'll look like this..... 👇🏻️

Dart
return Form(
  key: _keyForm,
  child: Padding(
    padding: const EdgeInsets.all(20),
    child: ListView(
      children: [
        Container(
          padding: const EdgeInsets.symmetric(vertical: 20),
          child: Text('Some inputs...'),
        ),
        TextFormField(
          controller: _name,
          decoration: InputDecoration(hintText: 'Insert your name.'),
          validator: (value) {
            if (value.isEmpty) return 'You have to insert a name';

            return null;
          },
          onSaved: (newValue) => _newUser.name = newValue,
        ),
        TextFormField(
          controller: _password,
          obscureText: true,
          decoration: InputDecoration(hintText: 'The password to log in.'),
          validator: (value) {
            if (value.length < 7)
              return 'Password must have at least 6 chars.';

            return null;
          },
          onSaved: (newValue) => _newUser.password = newValue,
        ),
        TextFormField(
          controller: _email,
          decoration:
              InputDecoration(hintText: 'E-mail to use for log in.'),
          validator: (value) {
            if (!value.contains('@gmail.com'))
              return 'Only gmail emails allowed.';

            return null;
          },
          onSaved: (newValue) => _newUser.email = newValue,
        ),
      ],
    ),
  ),
);

As you saw in the first image now when i will call the .validate() method it will call all the validators inside all our inputs and when i will call the .onSaved() method it'll do the same thing for the onSaved functions.

Now the last step is to add a button 'SAVE' that will call our function so we can execute those methods.

Dart

  void _saveForm(){

    if(_keyForm.currentState.validate()){

      _keyForm.currentState.save();

      print(_newUser.name);

    }

  }

  
  Widget build(BuildContext context) {
    return Form(
      key: _keyForm,
      child: Padding(
        padding: const EdgeInsets.all(20),
        child: ListView(
          children: [
            Container(...),
            TextFormField(...),
            TextFormField(...),
            TextFormField(...),
            RaisedButton(
              child: Text('SAVE'),
              onPressed: () {
                _saveForm();
              },
            )
          ],
        ),
      ),
    );
  }
}

Time to test 😃️

running _keyForm.currentState.validate() with wrong values.

The only thing that we have to do now is to click into the "SAVE" button.

The save button will call the _saveForm() function where...

We will check if _keyForm.currentState.validate() gives back true. In this case it's not since one or more of them are wrong.

As you can see it's working well, it shows the related errors if we are not in line with the validator.

Running _keyForm.currentState.save()

But... if the validate check gives us true we will enter the if statement and run currentState.save() that will run the save function inside all our inputs.

After that when we will print _newUser.name we will get the updated Instance.

As you can see in the image in the right it's all working fine!

Conclusion 

I hope that you enjoyed this article for more you can follow us here, if you have any question you will find us into the chat of Priiimo.com that you will find in the top right corner.

Bye 👋️

dart flutter tutorial forms
Expand your knowledge about this topic