Today, I’ll give some examples for creating forms in flutter. If you don’t know Flutter, you can start in here. The Flutter is a mobile SDK for creating mobile applications by fast. It can craft a application on iOS and Android devices with one code and this framework has full native performance!

A good news!

Flutter is in beta. Do not worry about beta because when Flutter in alpha, it used applications in production by Google. These applications downloaded and used by millions. Yes, Flutter is Google mobile UI Framework. Flutter using Dart language. It’s like Typescript or Javascript (my idea). And in the beta version, you can use Dart v2 in Flutter. I updated Flutter version in my computer using by this document. It’s easy.

Flutter has widgets for UI and we use Form and Field widgets today for creating a log in form. So first you need to look Flutter input widgets page. It has Form widget and FormField widget.

First, let’s create a Flutter project and cleanup starter project codes in main.dart file. Next, create a LoginPage class and _LoginPageState class in main.dart file. And add a appbar and sample text for showing the application.

Let’s look my code in this step.

import 'package:flutter/material.dart';

void main() => runApp(new MaterialApp(
  title: 'Forms in Flutter',
  home: new LoginPage(),
));

class LoginPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => new _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Login'),
      ),
      body: new Container(
        child: new Center(
          child: new Text('Hello world!')
        ),
      ),
    );
  }
}

Let’s give it a shot.

Step #1

Now, we are ready to add a form in this page. Let’s create a Form but be careful because we need a key for this Form because we will use this widget state in our class. So if you look at the Form Widget documents we have key property. So, we can use this for giving id of widget.

class _LoginPageState extends State<LoginPage> {
  final GlobalKey<FormState> _formKey = new GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Login'),
      ),
      body: new Container(
        padding: new EdgeInsets.all(20.0),
        child: new Form(
          key: this._formKey,
          child: new ListView(
            children: <Widget>[
              // We will add fields here.
            ],
          ),
        )
      ),
    );
  }
}

Now, we are ready to using this form but we need a class for passing your field values. So, let’s create a LoginData class with email and password properties. And add our field widgets and a submit button.

import 'package:flutter/material.dart';

void main() => runApp(new MaterialApp(
  title: 'Forms in Flutter',
  home: new LoginPage(),
));

class LoginPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => new _LoginPageState();
}

class _LoginData {
  String email = '';
  String password = '';
}

class _LoginPageState extends State<LoginPage> {
  final GlobalKey<FormState> _formKey = new GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    final Size screenSize = MediaQuery.of(context).size;

    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Login'),
      ),
      body: new Container(
        padding: new EdgeInsets.all(20.0),
        child: new Form(
          key: this._formKey,
          child: new ListView(
            children: <Widget>[
              new TextFormField(
                keyboardType: TextInputType.emailAddress, // Use email input type for emails.
                decoration: new InputDecoration(
                  hintText: '[email protected]',
                  labelText: 'E-mail Address'
                )
              ),
              new TextFormField(
                obscureText: true, // Use secure text for passwords.
                decoration: new InputDecoration(
                  hintText: 'Password',
                  labelText: 'Enter your password'
                )
              ),
              new Container(
                width: screenSize.width,
                child: new RaisedButton(
                  child: new Text(
                    'Login',
                    style: new TextStyle(
                      color: Colors.white
                    ),
                  ),
                  onPressed: () => null,
                  color: Colors.blue,
                ),
                margin: new EdgeInsets.only(
                  top: 20.0
                ),
              )
            ],
          ),
        )
      ),
    );
  }
}

Yes, we have UI components now. Let’s give it a shot.

Step #3

It’s cool. So we have UI components now but we have not any data or functionality for log in process. So, first we should validate this inputs for taking correct value. Flutter FormField widget has validator property. It’s so simple. This property need a function which return error string or null. And this function taking a input which is value of form field. So, we have 2 inputs which are email and password. I’m creating a two function for validating these fields and I’m using validate package for checking the value.

import 'package:validate/validate.dart'; // Add import for validate package.

class _LoginPageState extends State<LoginPage> {
  // Add validate email function.
  String _validateEmail(String value) {
    if (!Validate.isEmail(value)) {
      return 'The E-mail Address must be a valid email address.';
    }

    return null;
  }

  // Add validate password function.
  String _validatePassword(String value) {
    if (value.length < 8) {
      return 'The Password must be at least 8 characters.';
    }
    
    return null;
  }
}

Yes, we have validation functions now. So, we can validate the fields and save these field values to LoginData class. Finally, we need to add a handler function for submit button. We need to validate our form in this function and if everything okey, we can send our data where you want.

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

void main() => runApp(new MaterialApp(
  title: 'Forms in Flutter',
  home: new LoginPage(),
));

class LoginPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => new _LoginPageState();
}

class _LoginData {
  String email = '';
  String password = '';
}

class _LoginPageState extends State<LoginPage> {
  final GlobalKey<FormState> _formKey = new GlobalKey<FormState>();
  _LoginData _data = new _LoginData();

  String _validateEmail(String value) {
    // If empty value, the isEmail function throw a error.
    // So I changed this function with try and catch.
    try {
      Validate.isEmail(value);
    } catch (e) {
      return 'The E-mail Address must be a valid email address.';
    }

    return null;
  }

  String _validatePassword(String value) {
    if (value.length < 8) {
      return 'The Password must be at least 8 characters.';
    }

    return null;
  }

  void submit() {
    // First validate form.
    if (this._formKey.currentState.validate()) {
      _formKey.currentState.save(); // Save our form now.

      print('Printing the login data.');
      print('Email: ${_data.email}');
      print('Password: ${_data.password}');
    }
  }

  @override
  Widget build(BuildContext context) {
    final Size screenSize = MediaQuery.of(context).size;

    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Login'),
      ),
      body: new Container(
        padding: new EdgeInsets.all(20.0),
        child: new Form(
          key: this._formKey,
          child: new ListView(
            children: <Widget>[
              new TextFormField(
                keyboardType: TextInputType.emailAddress, // Use email input type for emails.
                decoration: new InputDecoration(
                  hintText: '[email protected]',
                  labelText: 'E-mail Address'
                ),
                validator: this._validateEmail,
                onSaved: (String value) {
                  this._data.email = value;
                }
              ),
              new TextFormField(
                obscureText: true, // Use secure text for passwords.
                decoration: new InputDecoration(
                  hintText: 'Password',
                  labelText: 'Enter your password'
                ),
                validator: this._validatePassword,
                onSaved: (String value) {
                  this._data.password = value;
                }
              ),
              new Container(
                width: screenSize.width,
                child: new RaisedButton(
                  child: new Text(
                    'Login',
                    style: new TextStyle(
                      color: Colors.white
                    ),
                  ),
                  onPressed: this.submit,
                  color: Colors.blue,
                ),
                margin: new EdgeInsets.only(
                  top: 20.0
                ),
              )
            ],
          ),
        )
      ),
    );
  }
}

Let’s give it a shot.

Final

If you enter correct values, you can see this data in console.

Console

That’s good.