You are on page 1of 5

4.

Angular arhitektura (komponente, direktive, binding)


4.1. Angular arhitektura
Osnovna celina za izgradnju Angular aplikacije je NgModule, koji pruža kontekst za
kompajliranje komponenti. NgModule prikuplјa povezani kod u funkcionalne skupove, a
Angular aplikacija je definisana skupom NgModule celina. Najjednostavnija aplikacija ima bar
jedan root modul koji omogućava njeno pokretanje, a praktične aplikacije imaju više feature
modula.
Komponente definišu poglede, odnosno prikaze (views), koji predstavlјaju skup elemenata
koje Angular može da bira i menja prema podacima i datoj logici programa. Svaka aplikacija
ima bar jednu root komponentu. Komponente koriste servise (services) koji pružaju
funkcionalnosti nevezane za prikaze. Provajderi servisa mogu se ugraditi (inject) u
komponente kao zavisnosti (dependency), čime se postiže modularanost i mogućnost
ponovnog korišćenja koda, kao i efikasanost.
I komponente i servisi su klase (class) sa dekoratorima (decorators) koji određuju njihov tip i
pružaju metapodatke koji govore Angular-u kako da ih koristi.
Metapodaci component klasu povezuju sa šablonom (template) koji definiše view. Ovaj šablon
kombinuje običan HTML sa Angular direktivama (directives) i binding markup-om koji
omogućava Angular-u da vrši izmene u HTML dokumentu pre nego što ga prikaže.
Metapodaci za service klasu pružaju Angular-u koje su neophodne kako bi se klasa učinila
dostupnom komponentama uz pomoć Dependency Injection (ID).
Komponente aplikacije definišu više hijerarhijski uređenih pogleda (views), a putanje za
navigaciju između njih omogućena Router servis.

Angular arhitektura: više detalјa možete videti ovde.


4.2. Moduli
Angular definiše NgModule, koji se razlikuje od EcmaScript2015 modula i praktično predstavlјa
njegov komplement. NgModule deklariše kontekst za kompajliranje skupa komponenti u
domenu aplikacije, tok rada ili skupa usko povezanih mogućnosti. NgModule komponente
mogu sa odgovarajućim kodom, kao što su servisi, formirati funkcionalne celine.
Svaka Angular aplikacija ima root module, pod nazivom AppModule, koja obezbeđuje
mehanizam za pokretanje aplikacije (bootstrapping). Tipična aplikacija može sadržati veći broj
funkcionalnih modula.
Kao i moduli kod EcmaScript2015, i NgModules mogu importovati ili eksportovati
funkcionalnosti. Na primer, da biste koristili Router servis u vašoj aplikaciji, jednostavno
importujete Router NgModule.
Ovakva podela na izraženo razdvojene funkcionalne module pomaže u projektovanju i izradi
složenih aplikacija, kao i kod dizajna za ponovno korišćenje određenih celina. Takođe, ovo
omogućava tzv. lazy-loading, tj. učitavanje modula na zahtev, čime se smanjuje obim koda koji
se učitava pri pokretanju aplikacije.
NgModule je praktično kontejner koji sadrži blok koda za određen domen funkcionalnosti
aplikacije, može sadržati komponente, provajdere servisa i drugi kod definisan unutar
NgModule komponente, a takođe može uvoziti funkcionalnosti iz drugim NgModule
komponenti.
Za više detalјa pogledati zvaničnu dokumentaciju, ali naravno, prema preporuci, sledećim
redosledom:
 EcmaScript6 in Depth: Modules
 JavaScript Modules vs. NgModules
 NgModules
 Architecture Overview – Introduction to Modules
4.3. Komponente
Svaka Angular aplikacija ima bar jednu komponentu, odnosno root komponentu koja povezuje
hijerarhiju komponenti sa DOM (Document Object Model) strane. Svaka komponenta definiše
klasu koja sadrži podatke i logiku aplikacije i povezana je sa HTML šablonom (template) kojim
je definisan view. Praktično, svaka komponenta ima bar 3 dokumenta, tj. fajla, istog naziva: .ts
(kod komponente), .html (HTML šablon) i .css (CSS stilovi za HTML šablon).
Odmah ispred klase je @Component dekorator koji identifikuje tu klasu kao komponentu i
pruža šablon i odgovarajuće metapodatke.
Kod JS-a dekoratori su funkcije koje menjaju JavaScript klase, dok Angular definiše određen
broj tih dekoratora koje klasama pridružuju specifične metapodatke, tako da Angular zna šta
su te klase i kako treba da funkcionišu.
Za više detalјa od komponentama pročitajte:
 Architecture Overviews – Introduction to Components
4.3.1. Templates, directives, data binding
Šabloni (template) kombinuju HTML i Angular markup tako da se HTML elementi mogu
menjati pre nego što se prikažu. Direktive (directives) pružaju programsku logiku, a binding
markup povezuje podatke i DOM.
Event binding omogućava interakciju tako što reaguje na unos od strane korisnika izmenom
odgovarajućih podataka, dok property binding omogućava da se u HMLT-u izmene ili prikažu
odgovarajućih vrednosti iz aplikacije.
Pre nego što se View prikaže ili izmeni, Angular izvršava direktive i razrešava povezanu sintaksu
sa šablonom kako bi izmenio odgovarajuće HTML elemente i DOM, a prema zadatom
programskom kodu i podacima. Angular podržava two-way data binding, što znači da izmene
u DOM-u, npr. izbor korisnika u formi i sl., mogu uticati na izmenu podataka u programu.
Na primer, pogledati jednostavnu Angular aplikaciju koja se podrazumevano kreira u okviru
novog projekta: https://angular.io/guide/quickstart
U ovom primeru app.component.html je HTML šablon (template) unutar koga postoji
{{ title }} markap umesto koga Angular upisuje vrednost koja je dodelјena za title unutar
osnovne komponente aplikacije: app.component.ts
4.3.2. Services
Kako bi se povećala modularnost i ponovna iskoristivost koda, Angular pored komponenti
uvodi i servise (Services), koji obuhvataju bilo kakvu vrednost, funkciju ili svojstvo potrebno
aplikaciji. Servis je uglavnom klasa koja ima usko ograničenu u dobro definisanu ulogu.
 Odvajanjem funkcionalnosti komponente vezanih za prikaz od drugih vrsta procesa
klase komponente postaju jednostavnije i efikasnije. U idealnom slučaju, zadatak
komponente je da omogući korisniku kvalitetno iskustvo u korišćenju interfejsa i ništa
više, a potrebno je da podrži atribute i metode za povezivanje podataka u cilјu
posredovanja između prikaza (view – rendered by template) i aplikativne logike (koja
često uklјučuje neke detalјe iz modela).
 Komponenta ne bi trebala da definiše stvari kao što su dovlačenje podataka sa servera,
validaciju unosa od strane korisnika ili ispisivanje logova na konzoli. Umesto toga, može
te zadatke da delegira servisima, koje mogu koristiti i druge komponente, naročito ako
se definišu preko injektivne (injectable) klase servisa. Takođe se aplikacija može učiniti
prilagodlјivom različitim okolnostima pomoću injektovanja različitih provajdera
određenog servisa.

Angular ne nameće ove principe, već pomaže da se prateći ove principe realizuje podela
aplikacione logike na servise i da se oni kroz dependency injection učine dostupnim
komponentama.

U sledećem kodu je dat jedan primer za servis klasu, koja ispisuje logove na konzoli.
export class Logger {
log(msg: any) { console.log(msg); }
error(msg: any) { console.error(msg); }
warn(msg: any) { console.warn(msg); }
}

Servisi mogu zavisiti od drugih servisa, pa na primer HeroService iz primera koji ćemo raditi
detalјnije zavisi od Logger i BackendService servisa, dok npr. BackendService može zavisiti od
drugih servisa, kao što je npr. HttpClient servis za dovlačenje podataka sa servera.
export class HeroService {
private heroes: Hero[] = [];

constructor(
private backend: BackendService,
private logger: Logger) { }

getHeroes() {
this.backend.getAll(Hero).then( (heroes: Hero[]) => {
this.logger.log(`Fetched ${heroes.length} heroes.`);
this.heroes.push(...heroes); // fill cache
});
return this.heroes;
}
}

4.4. Dependency Injection (DI)


Komponente konzumiraju servise, tj. moguće je injektovati (inject) servis u komponentu dajući
tako komponenti pristup servis klasi.
Angular koristi @Injectable dekorator za metapodatke na osnovu kojih se se klasa injektuje u
komponentu kao dependency. Slično se @Injectable koristi i da komponenta ili druga klasa
(kao npr. drugi service, pipe ili NgModule) ima zavisnost (has a dependency), pa dependency
ne mora biti samo servis, može biti i neka funkcija ili npr. vrednost (pa se u širem smislu kaže
da su svi oni određena vrsta servisa).
Dependency Injection (DI) je praktično umrežen u Angular i koristi se svugde gde je potrebn
novu komponentu „obogatiti“ servisima i svime drugim što je potrebno.
 Injektor (Injector) je glavni mehanizam ovog procesa. Programer ne mora kreirati
injektor, jer se on kreira na nivou cele aplikacije prilikom pokretanja.
 Injektor održava kontejner (Container) za instance zavisnosti koje su već kreirane, i
koristi ih ponovo ako je to moguće (npr. za druge komponente).
 Provajder (Provider) je kao recept za kreiranje dependency. Za servis je ovo tipično
sama servis klasa, dok za bilo koju zavisnost u aplikaciji provajder mora da se registruje
sa injektorom aplikacije, tako da injektor koristi tu zavisnost za kreiranje novih instanci.
Kada Angular kreira novu instancu komponent klase, određuje koji servisi i druge zavisnosti
komponenta zahteva, a na osnovu parametara konstruktora. Na primer, konstruktor
HeroListComponent zahteva HeroService.
constructor(private service: HeroService) { }

Kada Angular detektuje ovu zavisnost komponente od servisa, prvo proverava da li injektor
već ima neku postojeću instancu tog servisa. Ako ne postoji nijedna instanca traženog servisa,
injektor kreira novu instancu preko registrovanog provajdera, dodaje je injektoru i potom
vraća taj servis Angular serveru. Kada se razreše sve zavisnosti od servisa, Angular poziva
konstruktor komponente sa tim servisima kao argumentima/parametrima.
Proces injektovanja HeroService u komponentu servisa prikazan je na sledećoj slici.
Za svaki servis koji ćemo koristiti mora se registrovati bar jedan provajder (provider), a
provajder se može registrovati u modulu ili komponenti.
Kada se provajder dodaje root modulu, ista instanca servisa je dostupna svim komponentama
aplikacije.
Inicijalno, kada se kreira podrazumevani projekat, stavka „providers: []“ je prazna, tj. ne sadrži
nijedan servis. Ako su nam potrebni npr. BackendService, HeroService i Logger, dodajemo ih u
dekorator root modula:
providers: [
BackendService,
HeroService,
Logger
]
Kada se provajder registruje na nivou komponente, tada se za svaku instancu komponente
kreira nova instanca servisa. Kod komponente servisi se registruju unutar „providers“ atributa
@Component dekoratera:
@Component({
selector: 'app-hero-list',
templateUrl: './hero-list.component.html',
providers: [ HeroService ]
})

Više detalјa o Dependency Injection (DI) pročitajte na strani DI by example.

You might also like