[{"data":1,"prerenderedAt":22},["ShallowReactive",2],{"articolo-form-e-validazione-in-flutter-guida-completa-a-form-textformfield-e-validazione-avanzata":3,"comments-article-form-e-validazione-in-flutter-guida-completa-a-form-textformfield-e-validazione-avanzata":21},{"id":4,"title":5,"slug":6,"excerpt":7,"body":8,"cover_image":9,"video_url":10,"status":11,"published_at":12,"meta_title":13,"meta_description":14,"category":15,"author":19},10,"Form e validazione in Flutter: guida completa a Form, TextFormField e validazione avanzata","form-e-validazione-in-flutter-guida-completa-a-form-textformfield-e-validazione-avanzata","Impara a costruire form robusti in Flutter usando il widget Form, gestire la validazione in tempo reale, salvare i dati e creare validatori riutilizzabili per le tue app.","## Introduzione\n\nLa raccolta di dati dall'utente è uno dei compiti più comuni nello sviluppo di applicazioni mobili: schermate di login, registrazione, checkout, profili. Flutter offre un sistema potente e flessibile per gestire i form attraverso il widget `Form` e i campi `TextFormField`. In questo articolo vedremo come costruire form solidi, validare gli input e organizzare il codice in modo pulito e riutilizzabile.\n\n## I componenti fondamentali\n\nIl sistema dei form in Flutter si basa su tre elementi principali:\n\n- **`Form`**: un widget contenitore che raggruppa più campi e ne coordina validazione, salvataggio e reset.\n- **`GlobalKey\u003CFormState>`**: una chiave che permette di accedere allo stato del form e invocare metodi come `validate()` o `save()`.\n- **`TextFormField`**: una versione di `TextField` integrata con il sistema di validazione.\n\n## Un primo form di login\n\nVediamo un esempio base con email e password:\n\n```dart\nclass LoginForm extends StatefulWidget {\n  const LoginForm({super.key});\n\n  @override\n  State\u003CLoginForm> createState() => _LoginFormState();\n}\n\nclass _LoginFormState extends State\u003CLoginForm> {\n  final _formKey = GlobalKey\u003CFormState>();\n  String _email = '';\n  String _password = '';\n\n  void _submit() {\n    final form = _formKey.currentState!;\n    if (form.validate()) {\n      form.save();\n      debugPrint('Email: $_email, Password: $_password');\n      \u002F\u002F Qui invieresti i dati al backend\n    }\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Form(\n      key: _formKey,\n      child: Column(\n        children: [\n          TextFormField(\n            decoration: const InputDecoration(labelText: 'Email'),\n            keyboardType: TextInputType.emailAddress,\n            validator: (value) {\n              if (value == null || value.isEmpty) {\n                return 'Inserisci una email';\n              }\n              final regex = RegExp(r'^[\\w.+-]+@[\\w-]+\\.[\\w.-]+$');\n              if (!regex.hasMatch(value)) {\n                return 'Email non valida';\n              }\n              return null;\n            },\n            onSaved: (value) => _email = value ?? '',\n          ),\n          TextFormField(\n            decoration: const InputDecoration(labelText: 'Password'),\n            obscureText: true,\n            validator: (value) {\n              if (value == null || value.length \u003C 6) {\n                return 'La password deve avere almeno 6 caratteri';\n              }\n              return null;\n            },\n            onSaved: (value) => _password = value ?? '',\n          ),\n          const SizedBox(height: 16),\n          ElevatedButton(\n            onPressed: _submit,\n            child: const Text('Accedi'),\n          ),\n        ],\n      ),\n    );\n  }\n}\n```\n\nIl flusso è semplice: `validate()` esegue tutti i validatori dei campi e mostra eventuali messaggi di errore; se restituisce `true`, `save()` invoca tutti i callback `onSaved`.\n\n## Strategie di validazione automatica\n\nDi default la validazione avviene solo quando chiamiamo `validate()`. Possiamo però configurare quando i campi si auto-validano tramite la proprietà `autovalidateMode`:\n\n```dart\nForm(\n  key: _formKey,\n  autovalidateMode: AutovalidateMode.onUserInteraction,\n  child: ...\n)\n```\n\nI valori disponibili sono:\n\n- **`disabled`** (default): nessuna validazione automatica.\n- **`always`**: valida ad ogni rebuild, anche prima dell'interazione.\n- **`onUserInteraction`**: valida solo dopo che l'utente ha modificato il campo, l'opzione più gradita dal punto di vista UX.\n\n## Validatori riutilizzabili\n\nScrivere la logica di validazione inline diventa rapidamente ripetitivo. Conviene creare funzioni riutilizzabili e componibili:\n\n```dart\nclass Validators {\n  static String? required(String? value, [String message = 'Campo obbligatorio']) {\n    if (value == null || value.trim().isEmpty) return message;\n    return null;\n  }\n\n  static String? email(String? value) {\n    if (value == null || value.isEmpty) return null;\n    final regex = RegExp(r'^[\\w.+-]+@[\\w-]+\\.[\\w.-]+$');\n    return regex.hasMatch(value) ? null : 'Email non valida';\n  }\n\n  static String? minLength(String? value, int length) {\n    if (value != null && value.length \u003C length) {\n      return 'Minimo $length caratteri';\n    }\n    return null;\n  }\n\n  \u002F\u002F Compone più validatori: si ferma al primo errore\n  static FormFieldValidator\u003CString> compose(\n      List\u003CFormFieldValidator\u003CString>> validators) {\n    return (value) {\n      for (final validator in validators) {\n        final result = validator(value);\n        if (result != null) return result;\n      }\n      return null;\n    };\n  }\n}\n```\n\nUtilizzo:\n\n```dart\nTextFormField(\n  validator: Validators.compose([\n    (v) => Validators.required(v),\n    Validators.email,\n  ]),\n)\n```\n\n## Gestire i controller\n\nQuando hai bisogno di leggere o modificare il testo programmaticamente, usa un `TextEditingController`. Ricorda sempre di rilasciarlo nel `dispose`:\n\n```dart\nfinal _emailController = TextEditingController();\n\n@override\nvoid dispose() {\n  _emailController.dispose();\n  super.dispose();\n}\n```\n\n## Focus e navigazione tra i campi\n\nPer migliorare l'esperienza utente puoi spostare il focus al campo successivo quando si preme \"invio\" sulla tastiera:\n\n```dart\nTextFormField(\n  textInputAction: TextInputAction.next,\n  onFieldSubmitted: (_) {\n    FocusScope.of(context).nextFocus();\n  },\n)\n```\n\nSull'ultimo campo puoi usare `TextInputAction.done` e invocare direttamente il submit.\n\n## Validazione asincrona\n\nUn caso comune è verificare la disponibilità di uno username sul server. I validatori di `TextFormField` sono sincroni, quindi serve un approccio leggermente diverso: si conserva un messaggio di errore nello stato e si chiama `setState` dopo la richiesta.\n\n```dart\nString? _usernameError;\n\nFuture\u003Cvoid> _checkUsername(String value) async {\n  final available = await api.isUsernameAvailable(value);\n  setState(() {\n    _usernameError = available ? null : 'Username già in uso';\n  });\n}\n\n\u002F\u002F Nel TextFormField\nTextFormField(\n  decoration: InputDecoration(\n    labelText: 'Username',\n    errorText: _usernameError,\n  ),\n  onChanged: (value) {\n    \u002F\u002F idealmente con debounce\n    _checkUsername(value);\n  },\n)\n```\n\nÈ consigliabile aggiungere un meccanismo di **debounce** per non inondare il server di richieste ad ogni tasto premuto.\n\n## Best practice\n\n- **Separa la logica di validazione** in una classe dedicata e testabile.\n- **Usa `autovalidateMode: AutovalidateMode.onUserInteraction`** per un feedback immediato ma non invasivo.\n- **Non dimenticare il `dispose`** dei controller per evitare memory leak.\n- **Valida sempre lato server**: la validazione client-side è solo un aiuto all'utente, non una garanzia di sicurezza.\n- **Considera pacchetti come `flutter_form_builder`** quando hai form complessi con molti campi di tipi diversi.\n\n## Conclusione\n\nIl sistema dei form di Flutter è semplice da apprendere ma sufficientemente flessibile per gestire scenari complessi. Partendo dal widget `Form` e dai `TextFormField`, e organizzando i validatori in modo riutilizzabile, puoi creare interfacce di inserimento dati robuste e con un'ottima esperienza utente. Con l'aggiunta della validazione asincrona e della gestione del focus, le tue schermate raggiungeranno la qualità delle migliori app native.","https:\u002F\u002Fflutter.it\u002Fstorage\u002Farticles\u002Fec194b1c-665f-47d3-bb8f-a8ce0fc53635.jpg",null,"published","2026-06-13T04:00:41+00:00","Form e validazione in Flutter: guida completa","Guida pratica ai form in Flutter: Form, TextFormField, validatori riutilizzabili, autovalidateMode, validazione asincrona e best practice.",{"id":16,"name":17,"slug":18},1,"Guide","guide",{"id":16,"name":20},"Flutter Bot",[],1781333425030]