> For the complete documentation index, see [llms.txt](https://guide-angular.wishtack.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://guide-angular.wishtack.io/angular/formulaires/reactive-forms/la-boite-a-outils-des-reactive-forms.md).

# La boite à outils des "Reactive Forms"

## `FormControl`

La classe **`FormControl`** **est une indirection permettant de contrôler et d'accéder à l'état** des "controls" de la vue *(e.g. `<input>`)*.

{% tabs %}
{% tab title="book-form.component.ts" %}

```typescript
export class BookFormComponent {

    bookTitleControl = new FormControl();
    bookDescriptionControl = new FormControl();

    submitBook() {
        console.log(this.bookTitleControl.value);
        console.log(this.bookDescriptionControl.value);
    }

}
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="book-form.component.html" %}

```markup
<input
    type="text"
    [formControl]="bookTitleControl">

<textarea [formControl]="bookDescriptionControl"></textarea>

<button
    type="submit"
    (click)="submitBook()">SUBMIT</button>
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
On obtient l'erreur suivante :

`Can't bind to 'formControl' since it isn't a known property of 'input'.`

... car l'`Input` `formControl` est ajouté via la "directive" `FormControlDirective` *(*[*https://github.com/angular/angular/blob/master/packages/forms/src/directives/reactive\_directives/form\_group\_directive.ts*](https://github.com/angular/angular/blob/master/packages/forms/src/directives/reactive_directives/form_group_directive.ts)*)* mais cette "directive" n'est pas importée nativement.

Pour profiter de la directive `FormGroupDirective`, **il faut importer le module `ReactiveFormsModule`** dans les modules contenant des composants qui en dépendent.

```typescript
import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
    ...
    imports: [
        ReactiveFormsModule
    ]
})
export class BookModule {
}
```

**Vous pouvez retirer l'import du module `FormsModule`.**
{% endhint %}

`FormControl` fournit différentes propriétés et méthodes permettant de piloter le "control" :

* **`value`** : permet d'accéder à la valeur actuellement contenu dans le "control".
* **`valueChanges`** : est un `Observable` permettant d'**observer les changements** de valeur du "control".
* **`reset`**, **`setValue`** et **`patchValue`** permettent de modifier l'état et la valeur du "control".

{% hint style="danger" %}
La propriété `value` est une source dynamique de données et elle est donc de type `any`.

Méfiez-vous en lors de son utilisation car elle est donc compatible avec tous les types et vous ne serez donc pas "protégé" par la compilation TypeScript.
{% endhint %}

## `FormGroup`

`FormGroup` permet de **regrouper des "controls"** afin de faciliter l'implémentation, récupérer la valeur groupée des "controls" ou encore appliquer des validateurs au groupe.

Le `FormGroup` est construit avec un "plain object" associant chaque **propriété** à un **`FormControl`** .\
Il est alors possible d'accéder aux valeurs et aux "controls" via la propriété associée.

{% tabs %}
{% tab title="book-form.component.ts" %}

```typescript
export class BookFormComponent {

    bookForm = new FormGroup({
        title: new FormControl(),
        description: new FormControl()
    });

    submitBook() {
        console.log(this.bookForm.value);
    }

}
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="book-form.component.html" %}

```markup
<input
        type="text"
        [formControl]="bookForm.controls.title">

<textarea [formControl]="bookForm.controls.description"></textarea>

<button
        type="submit"
        (click)="submitBook()">SUBMIT</button>
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
L'objet `this.bookForm.value` présente l'ensemble des valeurs des controls via un "plain objet" :\
`{title: 'TITLE', description: null}`
{% endhint %}

{% hint style="success" %}
Pour éviter d'accéder aux controls via la propriété `FormGroup.controls`, les "Reactive Forms" implémentent également une directive `FormGroupDirective` qui permet d'**associer un `FormGroup` à un élément du DOM** ***(`form` en général mais on peut utiliser d'autres éléments)***. Cela permet alors d'associer les "controls" via leur nom à l'aide de l'`Input` `formControlName`.

```markup
<form
        [formGroup]="bookForm"
        (ngSubmit)="submitBook()">

    <input
            type="text"
            formControlName="title">

    <textarea formControlName="description"></textarea>

    <button type="submit">SUBMIT</button>

</form>
```

{% endhint %}

La classe **`FormGroup`** propose de nombreuses **propriétés et méthodes similaires** à celles rencontrées précédemment avec **`FormControl`**. En effet, **`FormControl` et `FormGroup` héritent de la classe abstraite `AbstractControl`**.

Un `FormGroup` est donc également un "control" et il est donc possible de construire une **arborescence de `FormGroup`**&#x73; afin de **regrouper différentes parties d'un formulaire de taille importante** ou dont des parties sont **réutilisables dans d'autres contextes**.

```typescript
new FormGroup({
    address: new FormGroup({
        street: new FormControl()
    })
});
```

## `FormArray`

`FormArray` héritant également de la classe abstraite `AbstractControl`, **permet de créer un "control" contenant une liste de "controls"** *(e.g. `FormControl` ou `FormGroup`)* **ordonnés** *(contrairement à `FormGroup` qui permet de créer un groupe de "controls" accessibles avec des clés sur un "plain object").*

La valeur contenu dans le `FormArray` est de type `Array`.

## `FormBuilder`

Le module `ReactiveFormsModule` implémente également un service `FormBuilder` qui permet d'ajouter un peu de "syntactic sugar" afin de **simplifier la création des `FormGroup`, `FormArray` ou `FormControl`**.

```typescript
bookForm: FormGroup;

constructor(private _formBuilder: FormBuilder) {
    this.bookForm = this._formBuilder.group({
        title: null,
        description: null
    });
}
```

�
