> 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/stan-modeli-ta-validaciya.md).

# Стан моделі та валідація

### &#x20;**Стан моделі**

Застосування директиви **ngModel** не тільки встановлює прив'язку даних, але і дозволяє відстежувати стан елемента вводу. Для встановлення стану Angular застосовує до елементів введення спеціальні CSS класи:

| Назви\_CSS\_класів | Опис                                                                                                                                     |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
| **ng-untouched**   | якщо елемент введення ще не отримував фокус                                                                                              |
| **ng-touched**     | якщо поле введення вже отримувало фокус, при цьому отримання фокусу не обов'язково повинно супроводжуватися зміною значення в цьому полі |
| **ng-dirty**       | якщо початкове значення в поле введення було змінено                                                                                     |
| **ng-pristine**    | якщо значення не змінювався з моменту завантаження сторінки                                                                              |
| **ng-valid**       | якщо значення в полі введено коректно                                                                                                    |
| **ng-invalid**     | якщо значення в полі введено НЕ коректне                                                                                                 |

Приклад:

```html
<input name="title" [(ngModel)]="title" />
```

В браузері:

{% code overflow="wrap" %}

```html
<input class="ng-untouched ng-pristine ng-valid" name="title" ng-reflect-name="title" />
```

{% endcode %}

### **Валідація**

В Angular ми можемо використовувати валідацію HTML5, яка застосовується у вигляді атрибутів.

Наприклад:

* **required** - поле обов'язкове для заповнення.
* **pattern** - задає регулярний вираз, якому повинні відповідати введені дані.

### &#x20;**NgForm**

Як правило, при роботі з формами, всі елементи введення не визначаються самі по собі, а поміщаються в стандартний елемент форму - `<form></form>`. Застосування даного елемента дозволяє управляти всіма елемента вводу в цілому як однією загальною формою.

Безпосередньо в Angular для роботи з формами визначена спеціальна директива **NgForm**. Вона створює об'єкт **FormGroup** і прив'язує його до форми, що дозволяє відстежувати стан форми, управляти її валідацією.

```html
<form #myForm="ngForm"></form>
```

## Завдання.

* Зверстати форму для додавання нового todo.
* Додати стилі та функціонал.
* Поле "Todo Title" повинно бути обов'язкове для заповнення.
* Форма не повинна відправлятися, якщо вона є невалідна (якщо дані в поля форми введені не правильно).

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

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

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

{% endcode %}
{% endtab %}

{% tab title="new-todo.component.html" %}
{% code overflow="wrap" lineNumbers="true" %}

```markup
<form class="app-new-todo"
      #newTodoForm="ngForm"
      (ngSubmit)="onSubmit()">
  <div class="form-group">
    <input class="form-control"
           placeholder="Todo title"
           name="title"
           type="text"
           #newTodoTitle="ngModel"
           [(ngModel)]="title"
           required
           [ngClass]="{
                'is-invalid': newTodoTitle.invalid && (newTodoTitle.dirty || newTodoTitle.touched),
                'is-valid': newTodoTitle.valid && (newTodoTitle.dirty || newTodoTitle.touched)
              }" />
  </div>

  <div class="form-group">
    <textarea class="form-control"
              rows="3"
              placeholder="Description"
              name="description"
              [(ngModel)]="description">
      </textarea>
  </div>

  <footer>
    <button class="btn btn-primary"
            type="submit"
            [disabled]="newTodoForm.invalid">
      Create
    </button>
  </footer>
</form>
```

{% endcode %}
{% endtab %}

{% tab title="new-todo.component.ts" %}
{% code overflow="wrap" lineNumbers="true" %}

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


@Component({
  selector: 'app-new-todo',
  templateUrl: './new-todo.component.html',
  styleUrls: ['./new-todo.component.css']
})
export class NewTodoComponent implements OnInit {.
  @ViewChild('newTodoForm') newTodoForm: FormGroup;

  title: string;
  description: string;

  constructor() { }

  ngOnInit(): void {
  }

  onSubmit(): void {
    console.log({
      title: this.title,
      description: this.description
    })

    this.newTodoForm.reset();
  }

}
```

{% endcode %}
{% endtab %}

{% tab title="new-todo.component.css" %}
{% code overflow="wrap" lineNumbers="true" %}

```css
.app-new-todo {
  padding-top: 20px;
  padding-bottom: 20px;
}

.app-new-todo footer {
  display: flex;
  justify-content: flex-end;
}
```

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

## Самостійна робота.

* Додати ще одну перевірку доля поля "Todo Title", кількість введених символів повинна бути більше двох.
* Використовуючи Bootstrap стилі, відобразити повідомлення для користувача чому поле не валіде.
