Angular: formularze wstęp + reactive forms
Opublikowano śro 23 grudnia 2020 w angular • 3 min read
Angular umożliwia stworzenie 2 rodzajów formularzy tzw. reaktywnych (reactive) oraz szablonowych (template-driven)
Reaktywne formularze -zapewniają bezpośredni dostęp do obiektów modelu. Są bardziej skalowalne i łatwiejsze w ponownym użytkowaniu. [forma walidacji: funkcja, przewidywalność: synchroniczna, model danych: ustrukturyzowany i niezmienny]
Szablonowe formularze - uzależnione są od dyrektyw w tworzeniu i manipulowaniu obiektu modelu. Są proste w implementacji w przypadku małych form. [forma walidacji: dyrektywy, przewidywalność: asynchroniczna, model danych: nieustrukturyzowany i mutowalny]
Zarówno formy reaktywne jak i szablonowe korzystają z poniższych klas, które stanowią o ich funkcjonowaniu
FormControl - śledzi wartość oraz status walidacji pojedynczego elementu formularza
FormGroup - śledzi wartości oraz status walidacji zbioru elementów formularza
FormArray - śledzi wartości oraz status zbioru walidacji tablicy zawierającej formularze
ControlValueAccessor - tworzy pomost pomiędzy instancjami Angular FormControl oraz natywnymi elementami drzewa DOM.
Dyrektywy
ngModel
dyrektywa ngModel jest częścią '@angular/forms' i jest z formularzami właśnie powiązana. Pozwala na dwustronne powiązanie [(ngModel)]
(w odróżnieniu od pojedynczego [ngModel]
np. w celu wskazania wartości początkowej/domyślnej), ale kiedy jest używana w pojedynce, wskazuje Angularowi, na element HTML, który ma kontrolować/ którego powinien być świadomy, w kontekście formularza oraz jego obsługi (patrz ngSubmit) - tworzy obiekt związany z formularzem. (patrz również poniżej Lokalna referencja + ngModel)
<input type="text" id="name" name="name" class="form-control" ngModel>
<input
class="col s8"
type="text"
placeholder="Dodaj zadanie i datę wykonania"
[(ngModel)]="taskName"
/>
ngSubmit
dyrektywa ngSubmit pozwala na połączenie z wydarzeniem, które ma zostać wykonane w trakcie wysyłania formularza - zapobiega wysłaniu formularza i wywołuje właściwe zdarzenie.
<form (ngSubmit)="onSubmit()">
ngModelChange
Lokalna referencja
#form = "ngForm"
- tworzy lokalną referencję (#form) do szablonu formularza poprzez wykorzystanie słowa kluczowego (ngForm) oraz obiektu formularza utworzony przez Angular (patrz ngModel).
// html
<form (ngSubmit)="onSubmit(form)" #form="ngForm">
// ts
onSubmit(submittedForm: {}) {
console.log(submittedForm);
}
Lokalna referencja + ngModel
Przy pomocy lokalnej refencji oraz użyciu ngModel
w szablonie formularza wskazujemy Angularowi jaki element chcemy kontrolować/ do którego chcemy się podpiąć -> patrz span: jeśli input/element posiada jest invalid to wtedy zaistniej.
<div class="form-group">
<label for="name">Character name</label>
<input
type="text"
id="name"
name="name"
class="form-control"
ngModel
required
#nameCtrl="ngModel"
/>
<span class="help-block" *ngIf="nameCtrl.invalid">Please enter a character name!</span>
</div>
Podobny przypadek -> jeśli obiekt formularza posiada invalid = true to przycisk będzie niedostępny/disabled
<form (ngSubmit)="onSubmit(form)" #form="ngForm">
[...]]
<button class="btn btn-primary" type="submit" [disabled]="form.invalid">Add Character</button>
</form>
Przykład reactive form - model formularza jest bezpośrednio definiowany w klasie (wyraźny model formularza) - dyrektywa [formControl] łączy instancję FormControl do konkretnego elementu formy (widoku) poprzez wewnętrzną wartość "akcesorium" / model formularza jest źródłem prawdy
import { Component } from '@angular/core';
import { FormControl } from '@angular/forms';
@Component({
selector: 'app-reactive-favorite-color',
template: `
Favorite Color: <input type="text" [formControl]="favoriteColorControl">
`
})
export class FavoriteColorComponent {
favoriteColorControl = new FormControl('');
}
Przykład template-driven form - model formularza jest domniemany, dyrektywa NgModel tworzy i zarządza instancją FromControl dla danego elementu HTML / źródłem prawdy jest szablon html
import { Component } from '@angular/core';
@Component({
selector: 'app-template-favorite-color',
template: `
Favorite Color: <input type="text" [(ngModel)]="favoriteColor">
`
})
export class FavoriteColorComponent {
favoriteColor = '';
}
Do przeczytania -> Przepływ danych w formularzach: angular.io - Data flow in forms
Reaktywne formularze
1 - Postawowy formularz reaktywny / całe repo dostępne tutaj
Opis:
Importowanie modułu ReactiveFormsModule do app.module.ts
Komponent name-editor -> name-editor.component.ts/name-editor.component.html
2- Zarządzanie formularzem z wieloma elementami oraz zagnieżdżone formularze
Zarządzanie wieloma instancjami Kontroli Formularza (form control) w pojedynczej grupie -> wykorzystanie FormGroup
profile-editor.component.ts i profile-editor.component.html
Przykładowy zwracany obiekt ->
{firstName: "mike ", lastName: "tyson", address: {street: "uluru", city: "rock", state: "tn", zip: "0000"}}
Istnieją dwa sposoby na aktualizację wartości:
setValue() - zmienia całą wartość w odniesieniu do struktury grupy formularza
patchValue() - zmienia właściwość zdefiniowaną w obiekcie, który uległ zmianie w modelu formularza
setValue() pozwala na przechwycenie błędów w złożonych formularzach, podczas gdy patchValue nie przekazuje o nich informacji/nie reaguje na nie.
3 - Tworzenie formularza przy pomocy FormBuildera + Walidacja
Szablon HTML z dodaną walidacją ()
4 - Dynamicznie modyfikowany formularz przy pomocy FromArray (alternatywa dla FromGroup)
Szablon HTML wykorzystujący *ngFor
Przykładowe dane zwrotne ->
Value: { "firstName": "Mike", "lastName": "Tyson", "address": { "street": "Bronson", "city": "Tyson City", "state": "Nebula", "zip": "0000" }, "aliases": [ "mike@tyson.usa", "tyson@usa.mike", "bronson@tyson.mike" ] }
Istotne/dalsze informacje:
więcej na temat walidacji formularzy można dowiedzieć się tutaj angular.io Validating form input
Lista Klas oraz Dyrektyw formularza Angular.io reactive-forms-api
Źródła: