0
0
FlutterHow-ToBeginner · 4 min read

How to Create Form in Flutter: Simple Guide with Example

To create a form in Flutter, use the Form widget combined with TextFormField widgets for input fields. Wrap your input fields inside a Form and use a GlobalKey to manage validation and submission.
📐

Syntax

The basic syntax to create a form in Flutter involves using the Form widget with a GlobalKey<FormState> to manage the form state. Inside the form, use TextFormField widgets for user inputs. Each TextFormField can have a validator function to check input validity.

  • Form: Container for form fields.
  • GlobalKey<FormState>: Controls form state and validation.
  • TextFormField: Input field with validation support.
  • validator: Function to validate input.
dart
final _formKey = GlobalKey<FormState>();

Form(
  key: _formKey,
  child: Column(
    children: [
      TextFormField(
        validator: (value) {
          if (value == null || value.isEmpty) {
            return 'Please enter some text';
          }
          return null;
        },
      ),
      ElevatedButton(
        onPressed: () {
          if (_formKey.currentState!.validate()) {
            // Process data
          }
        },
        child: Text('Submit'),
      ),
    ],
  ),
)
💻

Example

This example shows a simple Flutter app with a form containing a single text input. It validates that the input is not empty and shows a message when the form is submitted successfully.

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

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Flutter Form Example')),
        body: Padding(
          padding: EdgeInsets.all(16),
          child: MyCustomForm(),
        ),
      ),
    );
  }
}

class MyCustomForm extends StatefulWidget {
  @override
  _MyCustomFormState createState() => _MyCustomFormState();
}

class _MyCustomFormState extends State<MyCustomForm> {
  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          TextFormField(
            decoration: InputDecoration(labelText: 'Enter your name'),
            validator: (value) {
              if (value == null || value.isEmpty) {
                return 'Please enter some text';
              }
              return null;
            },
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 16.0),
            child: ElevatedButton(
              onPressed: () {
                if (_formKey.currentState!.validate()) {
                  ScaffoldMessenger.of(context).showSnackBar(
                    SnackBar(content: Text('Processing Data')),
                  );
                }
              },
              child: Text('Submit'),
            ),
          ),
        ],
      ),
    );
  }
}
Output
A screen with an AppBar titled 'Flutter Form Example', a text input labeled 'Enter your name', and a Submit button. If the input is empty and Submit is pressed, an error message appears below the input. If valid, a snackbar with 'Processing Data' shows.
⚠️

Common Pitfalls

  • Not assigning a GlobalKey<FormState> to the Form widget, so validation cannot be triggered.
  • Forgetting to call _formKey.currentState!.validate() before processing data.
  • Not returning null from the validator when input is valid, which causes validation to fail.
  • Using TextField instead of TextFormField when validation is needed.
dart
/* Wrong way: No GlobalKey and no validation call */
Form(
  child: TextFormField(
    validator: (value) => value!.isEmpty ? 'Enter text' : null,
  ),
);

/* Right way: Use GlobalKey and validate on submit */
final _formKey = GlobalKey<FormState>();

Form(
  key: _formKey,
  child: Column(
    children: [
      TextFormField(
        validator: (value) => value!.isEmpty ? 'Enter text' : null,
      ),
      ElevatedButton(
        onPressed: () {
          if (_formKey.currentState!.validate()) {
            // proceed
          }
        },
        child: Text('Submit'),
      ),
    ],
  ),
);
📊

Quick Reference

  • Form: Wraps input fields to group them.
  • GlobalKey<FormState>: Controls form state and validation.
  • TextFormField: Input field with built-in validation support.
  • validator: Function returning error string or null.
  • _formKey.currentState!.validate(): Checks all validators and returns true if all valid.

Key Takeaways

Use a GlobalKey to manage and validate your form.
Wrap input fields inside a Form widget to group them logically.
Use TextFormField with a validator function for input validation.
Call _formKey.currentState!.validate() to trigger validation before submission.
Return null from validator when input is valid to avoid errors.