Steuere deine Eingabefelder mit TextEditingController und validiere jede Eingabe auf einmal, dank Form und TextFormField.
Diese Lektion in Kodokon öffnenEin Eingabefeld ohne Controller ist eine Blackbox. TextEditingController gibt dir die Kontrolle: Lies controller.text jederzeit aus, fülle das Feld vor, leere es nach dem Absenden oder lausche mit addListener auf jeden Tastendruck. Der Controller wird in einem State erstellt, niemals in build - sonst würde er bei jedem Rebuild neu erzeugt.
import 'package:flutter/material.dart';
class NicknameField extends StatefulWidget {
const NicknameField({super.key});
@override
State<NicknameField> createState() =>
_NicknameFieldState();
}
class _NicknameFieldState extends State<NicknameField> {
final _controller = TextEditingController();
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return TextField(
controller: _controller,
decoration: const InputDecoration(
labelText: 'Nickname',
border: OutlineInputBorder(),
),
onSubmitted: (value) => debugPrint(value),
);
}
}Sobald ein Screen mehrere Felder zu prüfen hat, greife zum Trio Form, GlobalKey<FormState> und TextFormField. Jedes Feld beschreibt seine Regel in validator: Die Funktion gibt eine Fehlermeldung zurück oder null, wenn alles in Ordnung ist. Ein Aufruf von validate() auf dem Key löst alle Validatoren auf einmal aus.
import 'package:flutter/material.dart';
class SignUpForm extends StatefulWidget {
const SignUpForm({super.key});
@override
State<SignUpForm> createState() => _SignUpFormState();
}
class _SignUpFormState extends State<SignUpForm> {
final _formKey = GlobalKey<FormState>();
final _emailController = TextEditingController();
@override
void dispose() {
_emailController.dispose();
super.dispose();
}
void _submit() {
if (_formKey.currentState!.validate()) {
debugPrint('Email: ${_emailController.text}');
}
}
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextFormField(
controller: _emailController,
keyboardType: TextInputType.emailAddress,
decoration: const InputDecoration(
labelText: 'Email',
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Required field';
}
if (!value.contains('@')) {
return 'Invalid address';
}
return null;
},
),
const SizedBox(height: 16),
FilledButton(
onPressed: _submit,
child: const Text('Create account'),
),
],
),
);
}
}Beim Klick auf den Button führt validate() jeden validator aus: Die zurückgegebenen Meldungen erscheinen rot unter den betreffenden Feldern, und die Methode gibt false zurück, wenn mindestens ein Feld ungültig ist. Deine Absende-Logik bleibt also hinter einem einzigen if - es ist unmöglich, ungültige Daten abzuschicken.