Formly logo

🎤 Angular Formly

Simplifier, structurer et maintenir vos formulaires Angular

1. Introduction

Formly logo
  • Formly est une librairie Angular permettant de générer des formulaires dynamiquement à partir d’une configuration JSON ou TypeScript.
  • Elle repose sur les Reactive Forms d’Angular, mais adopte une approche déclarative et centralisée.

🎯 Objectif principal

Réduire la duplication, améliorer la lisibilité et faciliter la maintenance des formulaires complexes.

2. Historique rapide

1

AngularJS

Création originale sous angular-formly 1.0.0 en 2014

2

Angular 2

Reprise et adaptation pour Angular moderne

3

Projet actif

Maintenu par la communauté avec plusieurs dizaines de milliers de téléchargements hebdomadaires sur npm

Compatibilités UI — Formly

Formly
Bootstrap
Material2
Ionic
PrimeNG
Kendo
NG-ZORRO

⚙️ Principe de fonctionnement

🧾 JSON

Configuration décrivant la structure des champs, leurs validations, conditions d’affichage et interactions.

➡️
Formly logo Formly

Interprète la configuration pour créer automatiquement les composants de formulaire Angular.

➡️
🧠 Reactive Form

Liaison automatique entre les champs du formulaire et le modèle de données, avec validation intégrée.

“Définir le quoi plutôt que le comment.”
Template HTML Sans Formly

      
Le prénom est obligatoire.
Le prénom doit contenir au moins 2 caractères.
Avec Formly

      

➡️ Toute la logique de rendu, de validation et d'affichage est déléguée au composant <formly-form>.

🧩 Exemple simple : champ texte

fields: FormlyFieldConfig[] = [
  {
    key: 'firstName',
    type: 'input',
    props: {
      label: 'Prénom',
      required: true,
      minLength: 2,
    },
    validation: {
      messages: {
        required: 'Le prénom est obligatoire',
        minlength: 'Le prénom doit contenir au moins 2 caractères',
      },
    },
  },
];
        

➡️ Ce bloc suffit à générer un champ réactif complet, avec validation, label, et messages d’erreur automatiques.

🧩 Exemple : champ Select avec Options

fields: FormlyFieldConfig[] = [
  {
    key: 'country',
    type: 'select',
    props: {
      label: 'Pays',
      required: true,
      options: [
        { label: 'France', value: 'FR' },
        { label: 'Belgique', value: 'BE' },
        { label: 'Suisse', value: 'CH' },
      ],
    },
  },
];
          

➡️ Un menu déroulant simple où Formly gère le rendu des balises <option> automatiquement.

🧩 Exemple : Options Asynchrones (Observable)

fields: FormlyFieldConfig[] = [
  {
    key: 'city',
    type: 'select',
    props: {
      label: 'Ville',
      options: this.cityService.getCities(), // Observable<{label, value}[]>
      valueProp: 'id',
      labelProp: 'name',
    },
  },
];
          

➡️ Formly gère nativement les Observables pour charger les données depuis une API, et vous permet de mapper facilement les clés avec valueProp et labelProp.

🧩 Exemple avancé : champ conditionnel

fields: FormlyFieldConfig[] = [
  {
    key: 'isCompany',
    type: 'checkbox',
    props: {
      label: 'Est-ce une société ?',
    },
  },
  {
    key: 'companyName',
    type: 'input',
    props: {
      label: 'Nom de la société',
      required: true,
    },
    hideExpression: '!model.isCompany', // ou 'hide: !model.isCompany'
  },
];
    

➡️ Le champ Nom de la société n’apparaît que si la case Est-ce une société ? est cochée. Formly gère automatiquement l’affichage conditionnel et les validations dynamiques.

🧩 Exemple avancé : Lifecycle Hooks

fields: FormlyFieldConfig[] = [
  {
    key: 'email',
    type: 'input',
    props: { label: 'Email' },
    hooks: {
      onInit: (field) => {
        field.formControl.valueChanges.subscribe(v => {
          console.log('Email a changé :', v);
        });
      },
    },
  },
];
          

➡️ Interagissez directement avec le FormControl généré grâce aux hooks (onInit, onChanges, onDestroy...) pour des comportements spécifiques complexes.

🧩 Exemple sans formly

this.form = this.fb.group({
  isCompany: [false],
  companyName: [''],
});

this.form.get('isCompany')?.valueChanges.subscribe((isCompany) => {
  const companyNameControl = this.form.get('companyName');
  if (isCompany) {
    companyNameControl?.setValidators([Validators.required]);
  } else {
    companyNameControl?.clearValidators();
    companyNameControl?.setValue('');
  }
  companyNameControl?.updateValueAndValidity();
 });
    

➡️ Le champ Nom de la société n’apparaît que si la case Est-ce une société ? est cochée. Ici, l’affichage conditionnel et la validation sont gérés manuellement via les Reactive Forms d’Angular (avec un *ngIf et des Validators dynamiques).

🎨 Personnalisation Formly

Aller au-delà des types de champs par défaut.

Custom Types

Créez votre propre composant Angular (ex: <app-slider>), étendez FieldType, et déclarez-le dans le module Formly.

Custom Wrappers

Entourez vos champs avec du HTML personnalisé (panels, cards, tooltips) sans modifier le champ lui-même.

🛠 Créer un Custom Type

// 1. Le composant Angular
@Component({
  selector: 'formly-field-custom-input',
  template: `
    
    
Erreur personnalisée
`, }) export class CustomInputComponent extends FieldType<FieldTypeConfig> {} // 2. Utilisation { key: 'myField', type: 'custom-input', props: { label: 'Mon Champ' } }
📦 Créer un Custom Wrapper

// 1. Le composant Angular (Wrapper)
@Component({
  selector: 'formly-wrapper-panel',
  template: `
    
{{ props.label }}
`, }) export class PanelWrapperComponent extends FieldWrapper {} // 2. Utilisation { key: 'myField', type: 'input', wrappers: ['panel'], props: { label: 'Mon Champ avec Panel' } }
🪄 expressionProperties (Réactivité)

fields: FormlyFieldConfig[] = [
  {
    key: 'amount',
    type: 'input',
    props: { type: 'number' },
  },
  {
    key: 'message',
    type: 'input',
    expressionProperties: {
      // Le label change selon la valeur de 'amount'
      'props.label': 'model.amount > 100 ? "Montant élevé" : "Montant normal"',
      // Désactivé si 'amount' est vide ou <= 0
      'props.disabled': '!model.amount || model.amount <= 0',
      // Ajout de classe dynamique
      'props.className': 'model.amount > 1000 ? "text-red-500" : ""'
    }
  },
];
          

➡️ expressionProperties permet d'évaluer dynamiquement presque n'importe quelle propriété du champ en fonction du model ou du formState.

Avantages & Limites de Formly

Formly simplifie la création de formulaires Angular : moins de code, maintenance simplifiée et réutilisation maximale. Voici un aperçu clair de ses points forts et des quelques limites à connaître.

✅ Avantages de Formly
  • 🧩 Configuration déclarative : les changements de champs et validations sont gérés par Formly, sans code supplémentaire
  • ⚡ Ajout ou modification de champs très simple via la configuration
  • 📍 Règles et validations centralisées, lisibles et testables
  • ♻️ Réutilisation facile des types de champs, wrappers et validators entre projets
  • 🌍 Support multi-UI : Material, Bootstrap, PrimeNG, Ionic…
  • ⏱ Time-to-market réduit : moins de code à maintenir et modifier
⚠️ Limites de Formly
  • 💻 Courbe d’apprentissage initiale pour comprendre la configuration JSON et les expressions dynamiques
  • 🧩 Pour des formulaires très simples, Formly peut sembler “overkill”
  • 📚 Documentation complète mais parfois complexe pour les cas avancés (wrappers, field types custom)
  • ⚙️ Personnalisation complexe des comportements très spécifiques peut nécessiter du code supplémentaire
GIF animé

Questions ?

GIF animé