> For the complete documentation index, see [llms.txt](https://koziuk-s.gitbook.io/angular-starter/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://koziuk-s.gitbook.io/angular-starter/angular-form/reactive-forms.md).

# Reactive Forms

Це новий підхід для роботи з формами в реактивному стилі.

Опис форми відбувається в компоненті у вигляді дерева об'єктів, після чого це дерево зв'язується з шаблоном. Всі маніпуляції (валідація, підписка на зміну значення та інше) відбуваються в компоненті, що робить роботу з формами більш гнучкішою, зручнішою та передбачуванішою.

Перш ніж використовувати реактивні форми в компонентах, нам потрібно імпортувати в головному модулі **AppModule** модуль **ReactiveFormsModule,** який дозволяє працювати з ними.

{% code title="app.module.ts" overflow="wrap" lineNumbers="true" %}

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

@NgModule({
  imports: [ ReactiveFormsModule, //... ]
  //...
})
//...

```

{% endcode %}

В реактивних формах використовуються 3 типи блоків:

* **FormControl** - одиничний контрол форми.
* **FormGroup** - група контролів форми
* **FormArray** - масив груп або контролів форми.

{% code overflow="wrap" lineNumbers="true" %}

```typescript
this.myForm : FormGroup = new FormGroup({
    'userName': new FormControl('Tom'),
    'userEmail': new FormControl()
});
```

{% endcode %}

Але описувати форми більш  зручніше, використовуючи спеціальний інструмент **FormBuilder**

{% tabs %}
{% tab title="app.component.ts" %}
{% code overflow="wrap" lineNumbers="true" %}

```typescript
import { Component } from '@angular/core';
import { FormGroup, FormBuilder } from '@angular/forms';

@Component({
 selector: 'my-app',
 templateUrl: './app.component.html',
 styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit  {
 myForm: FormGroup;

 constructor (
  private fb: FormBuilder
 ) {}
 
 ngOnInit(): void {
  this.myForm = this.fb.group({
    'userName': ['Tom'],
    'userEmail': []
  });
 }
 
 onSubmit(): void {
   console.log(this.myForm.value);
 }
}

```

{% endcode %}
{% endtab %}

{% tab title="app.component.html" %}
{% code overflow="wrap" lineNumbers="true" %}

```markup
<form [formGroup]="myForm"
      (ngSubmit)="onSubmit()">
  <div>
    <label for="name">имя</label>
    <input type="text" id="name" formControlName="userName" />
  </div>
  
  <div>
    <label for="email">email</label>
    <input type="text" id="email" formControlName="userEmail" />
  </div>
  
  <button type="submit">Submit</button>
</form>
```

{% endcode %}
{% endtab %}
{% endtabs %}

Валідація таких форми відбувається за допомогою списку статичних методів класу **Validators**

{% code overflow="wrap" lineNumbers="true" %}

```typescript
  this.myForm = this.fb.group({
    'userName': [
      'Tom',
      Validators.required
     ],
    'userEmail': [
      '',
      [
        Validators.required,
        Validators.email
      ]
    ]
  });
```

{% endcode %}

#### Виведення повідомлень про помилку

Отримати доступ до контрола в компоненті можна наступним чином

{% code overflow="wrap" lineNumbers="true" %}

```typescript
this.myForm.controls['userName']
```

{% endcode %}

Приклад виведення помилок

{% tabs %}
{% tab title="app.component.html" %}
{% code overflow="wrap" lineNumbers="true" %}

```markup
<form [formGroup]="myForm"
      (ngSubmit)="onSubmit()">
  <div>
    <label for="name">имя</label>
    <input type="text" id="name" formControlName="userName" />
    
    <div *ngIf="myForm.controls['userName'].invalid && myForm.controls['userName'].touched">
      <span *ngIf="myForm.controls['userName'].errors.required">
        Input is required.
      </span>
    </div>
  </div>
  
  <div>
    <label for="email">email</label>
    <input type="text" id="email" formControlName="userEmail" />
  </div>
  
  <button type="submit">Submit</button>
</form>
```

{% endcode %}
{% endtab %}

{% tab title="app.component.ts" %}

```
```

{% endtab %}
{% endtabs %}
