Avez-vous une question? (216) 97 656 803 hajjriadh@gmail.com
Flutter

Les autres champs de formulaire : liste, cases, boutons radio, date

Les autres champs de formulaire : liste, cases, boutons radio, date. Dans cette leçon du cours Flutter, vous apprendrez à : proposer un choix dans une liste avec DropdownButtonFormField ; utiliser des...

0 chapitres 0 QCM Accès gratuit
Dans cet article

À propos de ce cours

Les autres champs de formulaire : liste, cases, boutons radio, date. Dans cette leçon du cours Flutter, vous apprendrez à : proposer un choix dans une liste avec DropdownButtonFormField ; utiliser des boutons radio avec RadioGroup, une case à cocher et un interrupteur ; saisir une date avec showDatePicker ; rendre obligatoire un champ non textuel avec FormFieldbool.

Chapitre 8 — Les formulaires Flutter · Les autres champs de formulaire : liste, cases, boutons radio, date

🎯 Objectifs de la leçon
• proposer un choix dans une liste avec DropdownButtonFormField;
• utiliser des boutons radio avec RadioGroup, une case à cocher et un interrupteur ;
• saisir une date avec showDatePicker;
• rendre obligatoire un champ non textuel avec FormField<bool>.

1. Un formulaire, plusieurs types de champs

Liste déroulante, boutons radio, date, interrupteur et case à cocher
Aperçu reconstitué de l'écran (Material 3) : le code de la leçon produit cet affichage, aux couleurs du thème près.

2. La liste déroulante

String? _filiere;

DropdownButtonFormField<String>(
  initialValue: _filiere,                         // anciennement « value » (avant Flutter 3.35)
  decoration: const InputDecoration(labelText: 'Filière', prefixIcon: Icon(Icons.school)),
  items: const [
    DropdownMenuItem(value: 'DD', child: Text('Développement digital')),
    DropdownMenuItem(value: 'ID', child: Text('Infrastructure digitale')),
    DropdownMenuItem(value: 'GE', child: Text('Gestion des entreprises')),
  ],
  onChanged: (v) => setState(() => _filiere = v),
  validator: (v) => v == null ? 'Choisissez une filière' : null,
  onSaved: (v) => _filiere = v,
)

3. Boutons radio, interrupteur, case à cocher

enum Niveau { technicien, technicienSpecialise }
Niveau _niveau = Niveau.technicienSpecialise;
bool _annonces = true;

// Boutons radio : le RadioGroup gère la valeur choisie (Flutter 3.35 et plus)
RadioGroup<Niveau>(
  groupValue: _niveau,
  onChanged: (v) => setState(() => _niveau = v!),
  child: const Column(
    children: [
      RadioListTile(value: Niveau.technicienSpecialise, title: Text('Technicien spécialisé')),
      RadioListTile(value: Niveau.technicien, title: Text('Technicien')),
    ],
  ),
),

// Interrupteur
SwitchListTile(
  title: const Text('Recevoir les annonces par e-mail'),
  value: _annonces,
  onChanged: (v) => setState(() => _annonces = v),
),

Sur une version de Flutter antérieure à 3.35, RadioGroup n'existe pas : on place groupValue et onChanged directement sur chaque RadioListTile. Ces deux propriétés sont aujourd'hui marquées obsolètes.

4. Un champ obligatoire qui n'est pas du texte

FormField<bool>(
  initialValue: false,
  validator: (v) => v == true ? null : 'Vous devez accepter le règlement',
  builder: (field) => Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
      CheckboxListTile(
        value: field.value,
        onChanged: (v) => field.didChange(v),       // prévient le formulaire du changement
        title: const Text("J'accepte le règlement intérieur"),
        controlAffinity: ListTileControlAffinity.leading,
      ),
      if (field.hasError)
        Padding(
          padding: const EdgeInsets.only(left: 16),
          child: Text(field.errorText!,
              style: TextStyle(color: Theme.of(context).colorScheme.error, fontSize: 12)),
        ),
    ],
  ),
),

FormField<T> transforme n'importe quel widget en champ de formulaire : il reçoit un validator, participe à validate(), save() et reset(), et fournit au builder un objet field (valeur, erreur, didChange).

5. Une date

final _dateCtrl = TextEditingController();
DateTime? _naissance;

TextFormField(
  controller: _dateCtrl,
  readOnly: true,                                    // pas de clavier : on ouvre le calendrier
  decoration: const InputDecoration(labelText: 'Date de naissance', prefixIcon: Icon(Icons.calendar_today)),
  validator: (_) => _naissance == null ? 'Choisissez une date' : null,
  onTap: () async {
    final date = await showDatePicker(
      context: context,
      initialDate: DateTime(2007),
      firstDate: DateTime(1960),
      lastDate: DateTime.now(),
    );
    if (date != null) {
      setState(() {
        _naissance = date;
        _dateCtrl.text = '${date.day.toString().padLeft(2, '0')}/'
            '${date.month.toString().padLeft(2, '0')}/${date.year}';
      });
    }
  },
),
ℹ️ À retenir
• DropdownButtonFormField: items, initialValue, validator.
• Boutons radio : un RadioGroup autour de RadioListTile; interrupteur : SwitchListTile.
• Case obligatoire : FormField<bool> + CheckboxListTile + field.didChange.
• Date : champ en lecture seule + showDatePicker au toucher.

🛠 Activité 5 — L'inscription à un module

Mission : Réalisez l'écran de la figure 1 : filière, niveau, date de naissance, annonces, acceptation du règlement, et un résumé après validation.

Questions pour avancer (répondez dans votre compte rendu, puis appliquez dans votre projet) :

  1. Pourquoi utiliser un type enum pour le niveau plutôt que des chaînes « technicien » ? Que gagnez-vous si vous faites une faute de frappe ?
  2. Le stagiaire doit avoir au moins 15 ans. Où vérifiez-vous cette règle ? Comment calculez-vous l'âge à partir de la date choisie ?
  3. La case « règlement » non cochée doit bloquer l'envoi avec un message en rouge. Qu'arrive-t-il si vous oubliez field.didChange(v)?
  4. Appuyez sur « Effacer » (reset()) : quels champs reviennent à leur valeur de départ ? La date est-elle effacée ? Corrigez.
  5. Ajoutez la filière « Gestion » qui fait apparaître une deuxième liste « Option » (comptabilité, commerce). Comment affichez-vous ce champ seulement dans ce cas ?
  6. Affichez un résumé dans une AlertDialog après validation. Comment affichez-vous le niveau de façon lisible à partir de l'enum ?

Je vérifie / je rends :

  • ☐ Le code et deux captures : formulaire avec erreurs, puis résumé.

← Validation des e-mails dans FlutterTP 8 : De la maquette Figma à l'application Flutter – inscription en 3 écrans →