Angular - moduły, komponenty oraz dyrektywa ngModel

Autor podstrony: Krzysztof Zajączkowski

Stronę tą wyświetlono już: 5449 razy

Wstęp

Tematem przewodnim tej podstrony będzie głównie opis tworzenia komponentów, tego czym one są oraz powiązanej z komponentami dyrektywy ngModel. Również poruszę temat tworzenia modułów oraz ich powiązania z komponentami.

Zanim jednak przejdę do sedna sprawy, wypadałoby zacząć od odpowiedzenia sobie pokrótce na pytanie: czym są komponenty? Otóż najkrótsza odpowiedź na to pytanie jest taka, że komponenty stanowią połączenie kodu klasy (który steruje działaniem wyświetlanego widoku), kodu widoku zapisanego w formacie HTML, styli z nimi powiązanymi CSS, SCSS czy też SASS (w zależności od opcji wybranych przez użytkownika).

Tworzenie modułu

Każdy komponent musi zostać podpięty w jakimś module, który z kolei jest podpięty do modułu głównego. Bez tego żaden komponent nie będzie działał. Z tego też względu w nowym folderze warto utworzyć sobie nowy moduł w następujący sposób:

ng g m sub

Oczywiście konieczne jest wykonanie tego polecenia z poziomu folderu projektu src/app. Tak utworzony moduł będzie wyglądał mniej więcej tak:

import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; @NgModule({ // dyrektywa ngModel to dzięki niej dzieje się Angularowa magia declarations: [], // tutaj będą umieszczane deklaracje komponentów imports: [ CommonModule // tutaj będą importowane moduły ] }) export class SubModule { } // eksport modułu, tak aby można było go zaimportować w module głównym app.module.ts

Powyższy kod zapisany jest w utworzonym pliku sub.module.ts, wraz z którym utworzony został automatycznie nowy folder sub. I to do tego właśnie folderu będą wrzucane komponenty, serwisy, klasy i interfejsy, które są powiązane z tymże modułem.

Tworzenie pierwszego komponentu

W wcześniej wygenerowanym folderze sub można teraz oddać się niekończącej się rozkoszy utworzenia nowego komponentu o jakże dźwięcznej nazwie myFirst:

ng g c myFirst

Po wykonaniu powyższego polecenia z poziomu folderu utworzonego modułu sub w pliku sub-module.ts w deklaracjach pojawi się takie oto coś:

declarations: [MyFirstComponent],

Jak widać utworzony komponent automatycznie został podpięty do pierwszego napotkanego nadrzędnego modułu.

Sam moduł komponent podzielony na pliki został utworzony w oddzielnym folderze o nazwie my-first. Są więc tutaj następujące pliki:

My będziemy się skupiać głównie na plikach HTML i ts no i troszkę CSS. Zajrzyjmy więc łaskawym okiem do kodu pliku my-first.component.ts:

import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-my-first', // selektor, którego będzie można użyć do osadzenia komponentu w kodzie HTML przykład: <app-my-first></app-my-first> templateUrl: './my-first.component.html', // ścieżka do pliku html powiązanego z kodem klasy komponentu styleUrls: ['./my-first.component.css' // ścieżka do pliku css z stylami powiązanymi z plikiem HTML komponentu }) export class MyFirstComponent implements OnInit { constructor() { } ngOnInit() { // funkcja, którą Angular wywoła, gdy zmienne komponentu zostaną zainicjalizowane (uruchamiane raz krotko po utworzeniu komponentu } }

Ważne aby pamiętać, że zmienne publiczne klasy komponentu jak również i jej metody mogą być użyte w kodzie HTML, natomiast wszystkie zmienne czy funkcje nie wchodzące w skład klasy tegoż komponentu nie mogą być użyte w kodzie, gdyż ten jest przez Angular-a ściśle izolowany. To samo dotyczy się styli CSS, które mają zastosowanie i działanie tylko w obrębie danego komponentu.

Osadzanie komponentu w komponencie głównym

Pierwszy komponent został utworzony, aby można było zobaczyć rezultat jego działania należy go osadzić w kodzie HTML głównego komponentu, który znajduje się w pliku app.component.html. Osadzanie wygląda następująco:

<app-my-first></app-my-first>

To jednak nie wystarczy, trzeba jeszcze dodać komponent MyFirstComponent do eksportu w pliku sub.module.ts w następujący sposób:

import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { MyFirstComponent } from './my-first/my-first.component'; @NgModule({ declarations: [MyFirstComponent], imports: [ CommonModule ], exports: [ MyFirstComponentComponent ] }) export class SubModuleModule { }

Zaś w pliku app.module.ts do deklaracji dodać MyFirstComponent

Ponieważ w standardowo wygenerowanym komponencie nie ma zbyt wiele ciekawego kodu, po uruchomieniu w konsoli polecenia:

ng serve

W przeglądarce powinien pokazać się standardowy kod następującej treści:

my-first works!

Osadzanie elementu kodu TypeScript w kodzie HTML

Angular umożliwia bardzo łatwe osadzanie kodu TypeScript w kodzie strony HTML co z kolei umożliwia dynamiczne renderowanie jej treści. Dla przykładu w klasie MyFirstComponent dopiszę sobie jedno pole:

title: 'Tytuł strony';

by po chwili lub co najwyżej dwóch osadzić go w kodzie HTML w następujący sposób:

<h1>{{ title }}</h1>

Oczywiście możliwe jest wykonywanie prostych operacji matematycznych, czy wykorzystanie metod stworzonych w klasie komponentu. Nie jest możliwe jednak wykorzystanie np. funkcji z biblioteki Math, gdyż te pochodzą spoza tejże klasy. Oto przykładowe dwa dodatkowe pola numeryczne dodane do klasy:

nr1: number = 10; nr2: number = 20;

oraz proste działanie matematyczne osadzone w kodzie pliku HTML:

<p>Działanie matematyczne: nr1 + nr2 = {{ nr1 + nr2 }}</p>

Oczywisty (przynajmniej mam taką nadzieję) wynik to:

Działanie matematyczne: nr1 + nr2 = 30

Bindowanie zmiennych z kontrolkami HTML

Kolejny podstawowy mechanizm umożliwiający łatwą komunikację z użytkownikiem stanowi bindowanie dwukierunkowe. Oto przykładowa kontrolka, która została zbindowana z zmienną klasy komponentu:

<input type="number" [(ngModel)]="nr1"/><input type="number" [(ngModel)]="nr2"/> <p>Działanie matematyczne: nr1 + nr2 = {{ nr1 + nr2 }}</p>

Ponieważ wykorzystywane są tutaj elementy formularza konieczne jest w pliku sub.module.ts dodanie do importów FormsModule:

import { FormsModule } from '@angular/forms'; // importowanie FormsModule @NgModule({ declarations: [MyFirstComponent], imports: [ CommonModule, FormsModule // dodany modół ], exports: [ MyFirstComponentComponent ] }) export class SubModule { }

W ten oto sposób do dwóch kontrolek HTML-a zostały podpięte zmienne sterujące a wszystko to za sprawą dwukierunkowego bindowania z wykorzystaniem dyrektywy ngModel. Bindowanie dwukierunkowe oznacza, że podpięta zmienna ustawia wartość kontrolki i na odwrót, kontrolka ustawia wartość zmiennej. Poniższy wynik został uzyskany za pomocą czystego JavaScript-u w celu zasymulowania działania kodu Angulara.

Działanie matematyczne: nr1 + nr2 =

Dla porównania kod JavaScript wymieszany z HTML-em wygląda tak:

<div><input id="nr1" type="number" value="10"><input id="nr2" type="number" value="20"></div> <div>Działanie matematyczne: nr1 + nr2 = <span id="sum"></span> <script>function add() { document.querySelector('#sum').innerText = (parseInt(document.querySelector('#nr1').value) + parseInt(document.querySelector('#nr2').value)).toString(); } add(); document.querySelector('#nr1').addEventListener('change', add); document.querySelector('#nr2').addEventListener('change', add); </script>
Propozycje książek