Flutter-Formulare und Validierung

Dieser Abschnitt führt in die Erstellung, Validierung und Verarbeitung der Übermittlung von Formularen in Flutter ein.


TextFormField - Formulareingabe

TextFormField ist ein TextField, das speziell für Formulare entwickelt wurde, mit integrierter Unterstützung für Validierung.

Beispiel: Einfaches Formular

class LoginForm extends StatefulWidget {
  const LoginForm({super.key});

  @override
  State<LoginForm> createState() => _LoginFormState();
}

class _LoginFormState extends State<LoginForm> {
  // Formularschlüssel (zur Validierung)
  final _formKey = GlobalKey<FormState>();

  // Eingabe-Controller
  final _usernameController = TextEditingController();
  final _passwordController = TextEditingController();

  @override
  void dispose() {
    _usernameController.dispose();
    _passwordController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: Column(
        children: [
          // Benutzername-Eingabe
          TextFormField(
            controller: _usernameController,
            decoration: const InputDecoration(
              labelText: Benutzername,
              prefixIcon: Icon(Icons.person),
            ),
            // Validator
            validator: (value) {
              if (value == null || value.isEmpty) {
                return 'Bitte Benutzernamen eingeben';
              }
              if (value.length < 3) {
                return 'Benutzername muss mindestens 3 Zeichen lang sein';
              }
              return null;
            },
          ),
          const SizedBox(height: 16),
          // Passwort-Eingabe
          TextFormField(
            controller: _passwordController,
            obscureText: true,  // Passwort verbergen
            decoration: const InputDecoration(
              labelText: Passwort,
              prefixIcon: Icon(Icons.lock),
            ),
            validator: (value) {
              if (value == null || value.isEmpty) {
                return 'Bitte Passwort eingeben';
              }
              if (value.length < 6) {
                return 'Passwort muss mindestens 6 Zeichen lang sein';
              }
              return null;
            },
          ),
          const SizedBox(height: 24),
          // Absenden-Schaltfläche
          ElevatedButton(
            onPressed: _submit,
            child: const Text('Anmelden'),
          ),
        ],
      ),
    );
  }

  void _submit() {
    // Formular validieren
    if (_formKey.currentState?.validate() ?? false) {
      // Validierung erfolgreich
      print('Benutzername: ${_usernameController.text}');
      print('Passwort: ${_passwordController.text}');
      // An Server senden...
    } else {
      // Validierung fehlgeschlagen
      print('Formularvalidierung fehlgeschlagen');
    }
  }
}

Gängige Validatoren

Beispiel: Häufige Validierungsregeln

// Benutzername validieren
String? validateUsername(String? value) {
  if (value == null || value.isEmpty) {
    return 'Bitte Benutzernamen eingeben';
  }
  if (!RegExp(r'^[a-zA-Z0-9_]+$').hasMatch(value)) {
    return 'Darf nur Buchstaben, Zahlen und Unterstriche enthalten';
  }
  return null;
}

// E-Mail validieren
String? validateEmail(String? value) {
  if (value == null || value.isEmpty) {
    return 'Bitte E-Mail eingeben';
  }
  final emailRegex = RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$');
  if (!emailRegex.hasMatch(value)) {
    return Bitte geben Sie eine gültige E-Mail-Adresse ein;
  }
  return null;
}

// Passwortstärke validieren
String? validatePassword(String? value) {
  if (value == null || value.isEmpty) {
    return 'Bitte Passwort eingeben';
  }
  if (value.length < 8) {
    return 'Das Passwort muss mindestens 8 Zeichen lang sein';
  }
  if (!RegExp(r'[A-Z]').hasMatch(value)) {
    return 'Das Passwort muss mindestens einen Großbuchstaben enthalten';
  }
  if (!RegExp(r'[0-9]').hasMatch(value)) {
    return 'Das Passwort muss mindestens eine Zahl enthalten';
  }
  return null;
}

// Telefonnummer validieren
String? validatePhone(String? value) {
  if (value == null || value.isEmpty) {
    return 'Bitte Telefonnummer eingeben';
  }
  final phoneRegex = RegExp(r'^1[3-9]\d{9}$');
  if (!phoneRegex.hasMatch(value)) {
    return 'Bitte eine gültige Telefonnummer eingeben';
  }
  return null;
}

// Prüfen, ob Passwörter übereinstimmen
String? validateConfirmPassword(String? value, String password) {
  if (value == null || value.isEmpty) {
    return 'Bitte Passwort bestätigen';
  }
  if (value != password) {
    return 'Die beiden Passwörter stimmen nicht überein';
  }
  return null;
}

Komplexes Formularbeispiel

Beispiel: Registrierungsformular

class RegisterForm extends StatefulWidget {
  const RegisterForm({super.key});

  @override
  State<RegisterForm> createState() => _RegisterFormState();
}

class _RegisterFormState extends State<RegisterForm> {
  final _formKey = GlobalKey<FormState>();
  final _usernameController = TextEditingController();
  final _emailController = TextEditingController();
  final _phoneController = TextEditingController();
  final _passwordController = TextEditingController();
  final _confirmPasswordController = TextEditingController();

  bool _acceptTerms = false;

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          // Benutzername
          TextFormField(
            controller: _usernameController,
            decoration: const InputDecoration(labelText: Benutzername),
            validator: validateUsername,
          ),
          const SizedBox(height: 16),
          // E-Mail
          TextFormField(
            controller: _emailController,
            keyboardType: TextInputType.emailAddress,
            decoration: const InputDecoration(labelText: E-Mail),
            validator: validateEmail,
          ),
          const SizedBox(height: 16),
          // Telefonnummer
          TextFormField(
            controller: _phoneController,
            keyboardType: TextInputType.phone,
            decoration: const InputDecoration(labelText: 'Telefonnummer'),
            validator: validatePhone,
          ),
          const SizedBox(height: 16),
          // Passwort
          TextFormField(
            controller: _passwordController,
            obscureText: true,
            decoration: const InputDecoration(labelText: Passwort),
            validator: validatePassword,
          ),
          const SizedBox(height: 16),
          // Passwort bestätigen
          TextFormField(
            controller: _confirmPasswordController,
            obscureText: true,
            decoration: const InputDecoration(labelText: Passwort bestätigen),
            validator: (value) => validateConfirmPassword(
              value,
              _passwordController.text,
            ),
          ),
          const SizedBox(height: 16),
          // Den Bedingungen zustimmen
          CheckboxListTile(
            value: _acceptTerms,
            onChanged: (value) {
              setState(() {
                _acceptTerms = value ?? false;
              });
            },
            title: const Text(Ich stimme den Nutzungsbedingungen zu),
            controlAffinity: ListTileControlAffinity.leading,
          ),
          const SizedBox(height: 24),
          // Absenden-Schaltfläche
          ElevatedButton(
            onPressed: _acceptTerms ? _submit : null,
            child: const Text(Registrieren),
          ),
        ],
      ),
    );
  }

  void _submit() {
    if (_formKey.currentState?.validate() ?? false) {
      // Formular absenden
      print(Registrierung erfolgreich!);
    }
  }

  @override
  void dispose() {
    _usernameController.dispose();
    _emailController.dispose();
    _phoneController.dispose();
    _passwordController.dispose();
    _confirmPasswordController.dispose();
    super.dispose();
  }
}

Die Formularvalidierung sollte sowohl clientseitig (für die Benutzererfahrung) als auch serverseitig (zur Sicherheit) durchgeführt werden; verlassen Sie sich nicht ausschließlich auf die clientseitige Validierung.

Weitere Erweiterungen