Custom validators help check if user input is correct in ways built-in checks can't. They make sure your app gets good data.
0
0
Custom validators in Flutter
Introduction
When you want to check if a password has special rules like a number or symbol.
When you need to verify a username is not already taken or follows a pattern.
When you want to confirm an email address is in a specific format.
When you want to check a phone number matches your country's style.
When you want to give users clear messages about what is wrong with their input.
Syntax
Flutter
String? customValidator(String? value) { if (value == null || value.isEmpty) { return 'This field cannot be empty'; } if (!value.contains('@')) { return 'Must contain @ symbol'; } return null; // null means input is valid }
The validator function returns a String?. If it returns null, the input is valid.
If it returns a String, that string is shown as an error message.
Examples
Checks if password is at least 6 characters long.
Flutter
String? passwordValidator(String? value) { if (value == null || value.length < 6) { return 'Password must be at least 6 characters'; } return null; }
Ensures username is not empty and has no spaces.
Flutter
String? usernameValidator(String? value) { if (value == null || value.isEmpty) { return 'Username cannot be empty'; } if (value.contains(' ')) { return 'Username cannot contain spaces'; } return null; }
Sample App
This app shows a form with an email field. The custom validator checks if the email is empty or missing '@'. If invalid, it shows an error below the field. If valid, it shows a success message.
Flutter
import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: const Text('Custom Validator Example')), body: const Padding( padding: EdgeInsets.all(16), child: MyForm(), ), ), ); } } class MyForm extends StatefulWidget { const MyForm({super.key}); @override State<MyForm> createState() => _MyFormState(); } class _MyFormState extends State<MyForm> { final _formKey = GlobalKey<FormState>(); final _emailController = TextEditingController(); String? emailValidator(String? value) { if (value == null || value.isEmpty) { return 'Email cannot be empty'; } if (!value.contains('@')) { return 'Email must contain @'; } return null; } @override Widget build(BuildContext context) { return Form( key: _formKey, child: Column( children: [ TextFormField( controller: _emailController, decoration: const InputDecoration(labelText: 'Email'), validator: emailValidator, ), const SizedBox(height: 20), ElevatedButton( onPressed: () { if (_formKey.currentState!.validate()) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Email is valid!')), ); } }, child: const Text('Submit'), ), ], ), ); } }
OutputSuccess
Important Notes
Always return null from your validator when the input is valid.
Use TextFormField with a Form widget to use validators easily.
Call _formKey.currentState!.validate() to run all validators and check if form is valid.
Summary
Custom validators check user input with your own rules.
Return a string error message if input is wrong, or null if input is good.
Use validators inside TextFormField and call validate() to check.