A) Création d’un formulaire en pure DART :
Avec la notion de focus, de test de la valeur de la saisie, de champs numériques, de RAZ et d’annulation de la saisie en cours et avec un scrolling permettant de nombreux champs.
import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { const appTitle = 'Form Validation Demo'; return MaterialApp( title: appTitle, home: Scaffold( appBar: AppBar( title: const Text(appTitle), ), body: const MyCustomForm(), ), ); } } // Create a Form widget. class MyCustomForm extends StatefulWidget { const MyCustomForm({Key? key}) : super(key: key); @override MyCustomFormState createState() { return MyCustomFormState(); } } // Create a corresponding State class. // This class holds data related to the form. class MyCustomFormState extends State<MyCustomForm> { // Create a global key that uniquely identifies the Form widget // and allows validation of the form. // // Note: This is a GlobalKey<FormState>, // not a GlobalKey<MyCustomFormState>. final _formKey = GlobalKey<FormState>(); // Create a text controller and use it to retrieve the current value // of the TextField. final myTextValue = TextEditingController(); final myText2Value = TextEditingController(); final myNumValue = TextEditingController(); @override Widget build(BuildContext context) { // Build a Form widget using the _formKey created above. return Form( key: _formKey, child: SingleChildScrollView( padding: const EdgeInsets.all(8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ //-- Présentation du formulaire const Padding( padding: EdgeInsets.symmetric(horizontal: 8, vertical: 16), child: TextField( decoration: InputDecoration( border: OutlineInputBorder(), hintText: 'Enter a search term', ), ), ), Container( margin: EdgeInsets.all(15.0), child: Column( children: <Widget>[ //-- Premier champ de saisie TextFormField( autofocus: true, //-- indique la ligne traitée controller: myTextValue, //-- récupération de la valeur saisie //-- Affichage libellé et possibilité de RAZ decoration: InputDecoration( hintText: 'Enter a message', suffixIcon: IconButton( onPressed: myTextValue.clear, icon: Icon(Icons.clear), ), ), //-- Test si une valeur a été saisie validator: (value) { if (value == null || value.isEmpty) { return 'Please enter some text'; } return null; }, ), //-- Deuxième champ de saisie TextFormField( autofocus: true, controller: myText2Value, // The validator receives the text that the user has entered. validator: (value) { if (value == null || value.isEmpty) { //return 'Please enter some text'; myText2Value == ""; } //return null; }, ), //////////// TextFormField( autofocus: true, //controller: myText2Value, // The validator receives the text that the user has entered. validator: (value) { if (value == null || value.isEmpty) { //return 'Please enter some text'; // myText2Value == ""; } //return null; }, ), //////////// new TextFormField( autofocus: true, controller: myNumValue, decoration: new InputDecoration(hintText: 'Mobile Number'), keyboardType: TextInputType.phone, maxLength: 10, ), ///////////////////////////////// ], ), ), //-- Fin de container pour la marge du formulaire //////////////////////:::::::://///////////////// //-- BOUTONS Center( child: Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Padding( padding: const EdgeInsets.symmetric(vertical: 16.0), child: ElevatedButton( onPressed: () { // Validate returns true if the form is valid, or false otherwise. if (_formKey.currentState!.validate()) { // If the form is valid, display a snackbar. In the real world, // you'd often call a server or save the information in a database. ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Processing Data')), ); ////////////////// showDialog( context: context, builder: (context) { return AlertDialog( // Retrieve the text the that user has entered by using the // TextEditingController. content: Text("'" + myTextValue.text + "' et '" + myText2Value.text + "' : " + myNumValue.text), ); }, ); ////////////////// } }, child: const Text('Submit'), ), ), //////////////////// SizedBox(width: 5), Padding( padding: const EdgeInsets.symmetric(vertical: 16.0), child: ElevatedButton( onPressed: () { _formKey.currentState!.reset(); }, child: const Text('RAZ'), ), ), //////////////////// SizedBox(width: 5), Padding( padding: const EdgeInsets.symmetric(vertical: 16.0), child: ElevatedButton( onPressed: () { SystemNavigator.pop(); }, child: const Text('Cancel'), ), ), ////////////////////////// ], ), ), /////////////////////////////////// ], ), ), ); } }
Pour permettre d’éditer la valeur par défaut :
TextFormField(
autofocus: true,
controller: TextEditingController()..text = 'Your initial value',
onChanged: (text) => {},
)
DartPad exemple de formulaire avec validation incluse.
Ajout d’une sélection dans une liste avec : https://pub.dev/packages/select_form_field/example
Références :
https://docs.flutter.dev/cookbook/forms/validation
B) Création à l’aide de form_builder :