Reaktywna kontrolka formularza w Angular 9

Reaktywna kontrolka formularza Angular 9

W dzisiejszym artykule opiszę, jak zbudować własną, dedykowaną reaktywną kontrolkę formularza w Angular 9. Do budowy zaawansowanych formularzy wymagane jest niejednokrotnie tworzenie własnych pól tekstowych oraz pól wyboru. Angular umożliwia tworzenie reaktywnych pól formularzy, które możemy dowolnie rozwijać i modyfikować.

Przygotowanie projektu Angular 9

Instalacja Angular CLI

Na starcie musimy zainstalować środowisko Angulara, zalecana jest instalacja z uprawnieniami administratora. Odpalając komendę zainstalujemy Angular CLI:

Windows

npm install -g @angular/cli

Linux

sudo npm install -g @angular/cli

Angular CLI jest wykorzystywany do łatwego stworzenia projektu i jego rozbudowę – umożliwia szybkie tworzenie nowych modułów, komponentów, serwisów, dyrektyw itp. Możesz sprawdzić poprawność zainstalowanego oprogramowania wpisując:

ng version

W wyniku wykonania operacji dostaniemy jasny komunikat z wersją Angulara oraz jego zależnościami tak jak zostało zaprezentowane na poniższym obrazku.

Inicjalizacja projektu Angular 9

Pierwsze kroki w stworzeniu aplikacji w oparciu technologii Angular można znaleźć pod linkiem https://angular.io/cli/new. Tam jest dokładnie opisany każdy opcjonalny parametr, który przyspiesza tworzenie projektu. Ominąć konfiguracje naszego projektu możemy używając następującą komendę z parametrami:

ng new custom-control-tutorial –p=custom –styles=scss –routing=true

Pierwsza część ng new custom-control-tutorial tworzy nam domyślnie projekt Angularowy, następnie za pomocą parametru –p=custom wyznaczamy tag który domyślnie zostanie dodany do każdego komponentu w aplikacji. Do stylowania projektu został wybrany preprocesor SCSS, więc użyjmy –styles=scss i dodajmy startowy routing aplikacji z parametrem –routing=true.Na poniższym obrazku znajduje struktura naszego projektu, którą mamy dostać na koniec instalacji.

Reaktywna kontrolka formularza – tworzenie

Zaczynając pracę z Angular musimy odpalić projekt z konsoli przez npm start. Pod linkiem w http://localhost:4200 zobaczymy początkową stronę Angulara – są tam umieszczone linki do dokumentacji i pierwsze kroki. W komponencie app.component.html możemy usunąć całą zawartość, w przyszłości będziemy tu testować nasze reaktywne kontrolki.

Podepnij wymagane moduły

Wymagane jest załączenie modułów FormsModule oraz ReactiveFormsModule, dlatego że bez nich nie będziemy mogli obserwować zmian na elementach formularza. FormsModule udostępnia nam podstawowe podejście do pracy z Template-Driven formularzami. Ta metodyka opiera się na stosowaniu walidatorów przy użyciu atrybutów required pattern oraz połączeniu zdefiniowanych zmiennych z klasy z elementami HTML.

Natomiast ReactiveFormsModule jest alternatywnym podejściem walidacji i obsługi formularze za pomocą FormControl a FormGroup, które pozwalają dokładnie opisać zachowanie walidatorów, dynamiczne zarządzać wartościami pól oraz zdefiniować kiedy ma się walidować kontrolka formularza. Angular udostępnia podstawowe walidatory z modułu @angular/forms, więc nie ma potrzeby pisać wszystkiego od początku. Również można tworzyć własne walidatory, które łatwo się konfigurują w postaci funkcji i mogą być przekazane do FormControl.

Korzystając z zaleceń Angulara stworzymy globalny moduł który będzie udostępniał wszystkie niezbędne elementy w innych miejscach aplikacji. Komenda ng generate module shared wygeneruje nam module Shared w którym eksportujemy moduły związane z formami tak jak jest pokazane niżej.

Wygenerowany SharedModule musimy załączyć do wszystkich modułów gdzie będziemy pracować z formami, w naszym przypadku to jest AppModule.

Własna reaktywna kontrolka formularza – generowanie komponentu

Wzorując się na dokumentacji do generowania komponentów wykonajmy następującą linijkę w naszej konsoli ng generate /shared/components/input. Spowoduje to utworzenie nowego komponentu w strukturze projektu oraz natychmiast podłączy ten komponent do modułu w którym został on stworzony.

Żeby dostać dostęp do naszej kontrolki z rodzica musimy zaimplementować interfejs ControlValueAccessor. Kompilator będzie podpowiadał nam o zaimplementowaniu metod z interfejsu ControlValueAccessor.

Na początek możemy stworzyć puste metody w naszym komponencie writeValue(), registerOnChange() oraz registerOnTouched().

Kolejna funkcja na poniższym obrazku musi być zaimportowana w dekoratorze @Component w polu providers.

Ta metoda jest na tyle uniwersalna że możemy przekazywać instancje naszych komponentów z dowolnym typem. Obsługę wszystkich zmian wartości będziemy opisywać w metodzie writeValue i operować na zmiennej value. Teraz możemy uzupełnić nasze metody dodając następujące linijki kodu.

Teraz jak dojdzie do jakichś zmian ze strony naszej kontrolki musimy nasłuchiwać tę zmianę i emitować wartość do metody writeValue(value). W moim przypadku przy każdej zmianie wartości onInput jest wywołana metoda input która aktualizuje wartość oraz wywołuje funkcje zmiany wartości i przekazuje je do rodzica.

Obsługa zmian kontrolki w moim pliku HTML wygląda następująco:

Przetestować działanie kontrolki możemy w komponencie app.component.html. Zdefiniujmy wartość name = new FormControl(‘’) w metodzie onInit(), natomiast w HTML`u będziemy musieli przekazać jako atrybut tę nazwę.

Wpisując cokolwiek do naszej kontrolki dostaniemy dynamicznie zmieniający się tekst, który potwierdza poprawność zaimplementowanej kontrolki tak jak jest pokazane na poniższym gifie.

Angular również udostępnia walidacje, którą możemy wykorzystać do naszych elementów. W ten sam sposób co wyżej musimy zaimportować interfejs Validator wraz z metodą validate. Ta metoda przyjmuje całą kontrolkę i w sobie już zawiera obsługę błędów.

Stwórzmy przykładowy getter z domyślnymi komunikatami błędów na najpopularniejsze walidacje w Angularze. Tekst błędu możemy zwrócić do templatki HTML, używając interpolacji i odpowiednio ustrukturyzować nasz input z błędem.

A pokazywać błędy możemy np. sprawdzając następujący warunek na obrazku niżej.

Ostatecznie załączamy dostęp walidatorów z rodzica za pomocą funkcji niżej. I dołączamy do providerów w dekoratorze @Components.

Dodając tablice walidatorów do naszej kontrolki będziemy mogli obserwować wyświetlanie komunikatów oraz podświetlenie kontrolki

Podsumowanie – reaktywna kontrolka formularza w Angular 9

W danym przykładzie jest pokazana najprostsza implementacja reaktywnej kontrolki na polu input. Akurat tej metodologii możemy użyć również z dowolnymi rzeczami takimi jak kalendarze, timery, rangepickery i pozostałe zewnętrzne biblioteki. Dla skutecznego połączenia naszego rozwiązania z bibliotekami napisanymi w czystym JS`ie musimy do zapoznać się ze zdarzeniami w API i emitować zmiany do poznanych metod writeValue, fnOnChange oraz fnOnTouched. W taki sposób można modyfikować kod i pisać reużywalne biblioteki kontrolek w Angularze.

A teraz trochę backendu – koniecznie zajrzyj Jak użyć technologii GraphQL w frameworku NestJS?