Lect. Univ. Dr. Gabroveanu Mihai Absolvent Alexandra Ștefania Dan CRAIOVA 2018 UNIVERSITATEA DIN CRAIOVA FACULTATEA DE ȘTIINȚE DEPARTAMENTUL DE… [604317]

UNIVERSITATEA DIN CRAIOVA

FACULTATEA DE ȘTIINȚE
DEPARTAMENTUL DE INFORMATICĂ

LUCRARE DE LICENȚĂ

Coordonator științific
Lect. Univ. Dr. Gabroveanu Mihai

Absolvent: [anonimizat]
2018

UNIVERSITATEA DIN CRAIOVA

FACULTATEA DE ȘTIINȚE
DEPARTAMENTUL DE INFORMATICĂ

SINGLE PAGE APPLICATION
ÎN ANGULAR

Coordonator științific
Lect. Univ. Dr. Gabroveanu Mihai

Absolvent: [anonimizat]
2018

Cuprins
INTRODUCERE ………………………….. ………………………….. ………………………….. …………………. 5
CAPITOLUL 1 ………………………….. ………………………….. ………………………….. ……………………. 6
CONCEPTE GENERALE SPA ………………………….. ………………………….. ………………………… 6
1.1.SPA vs. design tradițional ………………………….. ………………………….. ………………………….. 6
1.2.Patternuri MV* ………………………….. ………………………….. ………………………….. …………….. 9
1.3.Navigarea în SPA ………………………….. ………………………….. ………………………….. ……….. 11
1.4. Comunicare cu serverul în SPA ………………………….. ………………………….. ……………….. 13
CAPITOLUL 2 ………………………….. ………………………….. ………………………….. ………………….. 15
TYPESCRIPT ÎN ANGULA R ………………………….. ………………………….. ………………………… 15
2.1. Limbajul TypeScript ………………………….. ………………………….. ………………………….. ….. 15
2.1.1. Tipuri de bază ………………………….. ………………………….. ………………………….. ……… 15
2.1.2. Funcții și tipurile funcțiilor ………………………….. ………………………….. ……………….. 17
2.1.2. Interfețe ………………………….. ………………………….. ………………………….. ……………… 18
2.1.3. Decoratori ………………………….. ………………………….. ………………………….. …………… 19
2.2. Compoziția componentelor în TypeScript ………………………….. ………………………….. …. 20
2.3. Client -side Routing pentru aplicații SPA ………………………….. ………………………….. …… 21
2.3.1. RouterModel ………………………….. ………………………….. ………………………….. ……….. 22
2.3.2 Router Directives ………………………….. ………………………….. ………………………….. ….. 23
CAPITOLUL 3 ………………………….. ………………………….. ………………………….. ………………….. 24
ANGULAR -CONCEPTE DE BAZĂ ………………………….. ………………………….. ………………. 24
3.1. Arhitectura unei aplicatii Angular ………………………….. ………………………….. …………….. 24
3.2. Module ………………………….. ………………………….. ………………………….. …………………….. 29
3.3. Componente ………………………….. ………………………….. ………………………….. ……………… 30
3.3.1. Comun icarea între componenta părinte și componenta copil ………………………….. 30
3.3.2. Ciclul de viață al componentelor ………………………….. ………………………….. ………… 32
3.4. Angular Router ………………………….. ………………………….. ………………………….. …………. 33
3.4.1. Blocuri importante ………………………….. ………………………….. ………………………….. .. 35
3.4.2. Route Guards ………………………….. ………………………….. ………………………….. ………. 36
3.5. Directive ………………………….. ………………………….. ………………………….. …………………… 37
3.6. Pipes ………………………….. ………………………….. ………………………….. ………………………… 38
3.7. Observable, HttpClient ………………………….. ………………………….. ………………………….. .. 40
3.8. Forme în Angular ………………………….. ………………………….. ………………………….. ………. 43
3.8.1. Template -driven forms ………………………….. ………………………….. ……………………… 43
3.8.2. Reactive forms ………………………….. ………………………….. ………………………….. …….. 44
APLICAȚIE – BALLROOM MANAGEMENT SYSTEM ………………………….. …………….. 46

4.1. Introducere ………………………….. ………………………….. ………………………….. ……………….. 46
4.2. Arhitec tura aplicației ………………………….. ………………………….. ………………………….. ….. 47
4.3. Structura bazei de date ………………………….. ………………………….. ………………………….. .. 49
4.4. Cazuri de utilizare ………………………….. ………………………….. ………………………….. ……… 50
4.5. Descriere aplicație – screenshoturi ………………………….. ………………………….. ……………. 52
CONCLUZII ………………………….. ………………………….. ………………………….. ……………………… 65
BIBLIOGRAFIE ………………………….. ………………………….. ………………………….. ……………….. 67

5

INTRODUCERE

Dezvoltatorii au urmărit în decursul timpului visul de a furniza aplicații web care să
împărtășească look and feel -ul aplicațiilor desktop native. Diferite soluții pentru o experiență
mai nativă, cum ar fi Iframes, Java applets, Adobe Flash și Microsoft Silverlight, au fost
încercate cu diferite grade de succes. Deși tehnologii diferite, toate au cel puțin un obiectiv
comun: aducerea puterii unei aplica ții desktop la mediul transversal a unui browser web.
Aplicația pe o singură pagină (web), sau SPA (Single Page A pplication), împărtășește
acest obiectiv, utilizând aceleași limbaje care sunt folosite în mod normal într -o aplicație web :
HTML, CSS și JavaScript, dar fară a necesita un plugin de browser sau un nou limbaj de
învățat.
În cazul unui utilizator, diferența se află în modul în care se va simți utilizărea unei
aplicații ce folosește arhitectura SPA , navigarea asemănân du-se cu cea a unei aplicații
desktop , scopul fiind acela de a economisii timpul utilizatorului prin evitarea reîncărcărilor
constante ale paginii web . Diferența pentru dezvoltator este aceea de a crea o aplicație care
funcționeză într -o singură pagină HTM L al cărei conținut va fi rescris la fiecare acțiune a
utilizatorului. Această nouă abordare crește viteza de performanță și o face mai ușor de testat .
Arhitectura SPA constituie una dintre cele mai recente evoluții în designul aplicațiilor
web, iar prin i ntermediul a diverse biblioteci JavaScript și tool -uri cum ar fi Jquery sau
Angular, permite dezvoltatorilor să creeze aplicații web care foarte rar apelează serverul
pentru a încărca o pagină HTML nouă. În schimb, pagina HTML unică este împărțită în
secțiuni și codul JavaScript care rulează în browserul web apelează API -uri diferite pe un
server care returnează datele. Bibliotecile JavaScript iau apoi aceste date și actualizează
pagina în conformitate cu logica de prezentare definită de dezvoltator in cadr ul aplicației.
Aplicațiile SPA elimină logica de prezentare din partea de server și o plasează în partea de
client, în browser.
Lucrarea de față își propune prezentarea celor mai importante aspecte ale designului și
arhitecturii SPA și punerea în evidență a acestora prin utilizarea platformei Angular care face
ma ușor de construit aplicațiile web .

6

CAPITOLUL 1
CONCEPTE GENERALE SPA

1.1. SPA vs. design tradițional

O aplicație SPA funcționează în interiorul unui browser și nu necesită reîncărcarea
paginii în timpul utilizării, menținând utilizatorul într -un spațiu web confortabil, în care
conținutul este prezentat într -un mod simplu, ușor și funcțional.
Într-o aplicaț ie SPA view -urile nu sunt pagini HTML complete. Sunt doar por țiuni din
DOM care alcătuiesc zonele vizibile ale ecranului. După încărcarea inițială a paginii, toate
instrumentele necesare pentru crearea și afișarea de view -uri sunt descărcate și gata de
utilizare. Dacă este necesar un nou view, este generat local în browser și atașat dinamic la
DOM prin JavaScript, nefiind necesare actualizări ale browserului web.
Temenul “aplicație cu o singură pagină” sau SPA este de obicei folosit pentru a
descrie aplicațiile care au fost construite pentru web. Aceste aplicații sunt accesate printr -un
browser web ca și alte site -uri web, dar oferă interacțiuni dinamice asemănătoare celor
întâlnite la aplicațiile mobile si desktop.
Cea mai importantă diferență dintre un site web obișnuit și o SPA este numărul redus
de reîmprospăta ri în pagină . SPA -urile au o utilizare mai mare a AJAX – o modalitate de a
comunica cu serverele back -end fără a face o reîmprospătare completă a paginii – pentru a
obține date încărcate în aplicați e. Ca rezultat, procesul de redare a paginilor are loc mai ales
pe partea clientului.
Într-o aplicație web tradițională, fiecare pagină HTML este construită pe server .
Atunci când sunt necesare date proaspete pe partea de client, cererea este trimisă către partea
de server, unde este intercepta tă, prelucrată, urm ând ca view -ul să fie returnat browserului sub
forma unei noi pagini HTML, și, prin intermediul unei actualizări a UI(refresh), ut ilizatorul va
vedea noua pagină ce conține datele solicitate.
Mutarea procesului de creare și gestionare a view -urilor în int erfața cu utilizatorul
conferă aplicațiilor SPA un avantaj interesant și anume acela că serverul nu mai este obligat
să se implice în modul în care sunt prezentate datele. Designul SPA general este aproape
același cu designul tradițional (Fig.1.1) . Modific ările cheie sunt următoarele : nu se
actualizează browserul complet, logica de prezentare se află în partea de client, iar tranzacțiile
pe partea de server pot fi numai date, depi nzând de preferințele de redare.

7

Figura 1.1. Comparație între designul SPA ș i cel traditional
(What -is-SPA-single -page -application)

Paginile aplicație SPA nu sunt pagini, cel puțin nu în sensul tradițional. Pe măsură ce
utilizatorul navighează, părțile ecranului care par a fi pagini sunt de fapt secțiuni independente
ale conținutului aplicației, denumite view -uri. Figura Fig. 1.2. prezintă un site web tradițional
format din două pagini, ambele conținând structura HTML completă, inclusiv HEAD și
BODY.
Figura Fig. 1.3. prezintă același site web sub forma unei aplicații SPA. Când aplicația
începe, framework -ul MVC inserează primul view, iar în momentul în care utilizatorul
navighează către ceea ce pare o nouă pagină, frameworkul schimbă primul view -ul cu cel de –
al doilea.

8

Figura 1.2. Site web traditional
(Emmit A. Scott J. , 2016, p. 34)

Figura 1.3. SPA site
(Emmit A. Scott J. , 2016, p. 35)

9
1.2. Patternuri MV*
Într-o aplicație SPA, păstrarea codului separat pe baza funcționalității sale este mai
mult decât o tehnică bună, este esențial pentru a putea implementa cu succes o astfel de
aplicație. Cheia pentru aceasta este crearea unei separări a rolurilor, preocupă rilor în cadrul
aplicației, separând de fapt diferitele aspecte ale codului pe baza responsabilității pe care o
are.
Modelele de separare a datelor, logicii și interfeței cu utilizatorul există de ani de zile,
unele dintre cele mai notabile fiind Model -View-Controller (MVC), Model -View -Presenter
(MVP) și Model -View -ViewModel (MVVM). În ultimii ani însă, aceste modele au început să
apară sub formă de biblioteci și frameworkuri JavaScript pentru a ajuta la aplicarea acelorași
concepte în partea de front -end a aplicațiilor web. Ideea de bază este că un framework sau o
bibliotecă gestionează relația dintre JavaScript și HTML. Bibliotecile si frameworkurile MV*
permit proiectarea intefeței cu utilizatorul astfel încât datele domeniului(modelul) și paginile
HTML rezultate , cu care interacționează utilizatorul(view -ul), pot comunica dar sunt
menținute separat în cod. Ultima componentă a patternului MV*, controllerul, prezentatorul
sau ViewModel -ul, acționează precum un orchestrator pentru toate acestea.
În MV *, M reprezintă mode lul-drept model servește starea aplicației, datele
comunicate spre view de către controller (prin directive sau direct) , iar V înseamnă
vizualizare – partea de afișare și interpretare expresii . Modelu l conține de obicei date, logica
aplicație i și logică de validare. Conceptual, ar putea reprezenta ceva asemănător unui client
sau unei plăți. Modelul nu este niciodată preocupat de modul în care sunt prezentate datele.
View -ul este ceea ce vede utilizatorul și lucrul cu care interacționează. Este o reprezentare
vizuală a datelor modelului. Poate fi o structură simplă car e se bazează pe alte părți ale
frameworkului pentru actualizări și răspunsuri la interacțiunile utilizatorilor sau poate conține
logică, în funcție de implementarea MV *.
Folosind modele arhitecturale pentru a separa datele, logica și reprezentarea rezultată a
ieșirii este o noțiune care a fost în jur de multă vreme. În centrul acestor modele de design este
ideea că codul unei aplicații este mai ușor de proiectat, dezvoltat și menți nut dacă este
segmentat pe baza tipului de responsabilitate pe care îl are fiecare strat.
Model -View -Controller (MVC) – este unul dintre cele mai vechi modele care încearcă
să separe datele, logica și prezentarea , având un rol esențial în proiectarea inter fețelor grafice
cu utilizatorul . De la înființare, modelul și variantele sale au devenit modele comune de
proiectare pentru toate tipurile de dezvoltare soft ware. MVC include modelul, vizualizarea și

10
un controler. Controlle rul este punctul de intrare al ap licației, primind semnale de la
comenzile din interfața cu utilizatorul , aici se găsește logica de control, captarea
evenimentelor, procesarea datelor înainte de serializare sau validarea formularelor . De
asemenea, conține logica care procesează intrarea u tilizatorului și trimite comenzi către model
pentru a -și actualiza starea bazată pe intrarea primită. Interacțiunile cu controllerul
declanșează un lanț de evenimente care, în cele din urmă, conduc la o actualizare a view -ului
atunci când apar modificări.
Model -View -Presenter (MVP) – Ideea din spatele acestui pattern a fost să decupleze
modelul de celelalte două componente ale MVC. În MVP, un obiect asemănător unui
controller și view -ul vor reprezenta interfața cu utilizatorul. Modelul va continua să reprez inte
gestionarea datelor, însă nu există un controller care să acționeze, fiecare view fiind susținut
de o componentă numită prezentator (presenter). Prezentatorul conține logica de prezentare a
view-ului. Această viziune răspunde numai la interacțiunile u tilizatorilor prin delegarea
responsabilității către prezentator. Prezentatorul are acces direct la model pe ntru orice
schimbări necesare, trimite datele schimbate înapoi în vi ew și își asumă sarcina de a actualiza
view-ul și modelul . În acest fel, acționează ca un "intermediar" între model și v iew.
Model -View -ViewModel (MVVM) – Ca și in MVP, punctul de intrare este view -ul iar
și acest model are un obiect care se află între model și view, purtând numele de ViewModel.
Acesta este un model sau o repre zentare a vi ew-ului în cod, pe lângă faptul că este puntea
dintre model și vi ew. Orice este necesar pentru a defini și a gestiona vi ew-ul este conținut în
ViewModel. Aceasta include proprietățile datelor , precum și logica de prezentare. Fiecare
punct de da te din model care trebuie să fie reflectat în vi ew este mapat la o proprietate de
potrivire în ViewModel. Ca un prezentator în MVP, fiecare vi ew este susțin ut de un
ViewModel care gestionează modificările din vi ew și de model, păstrându -le pe cele două
sincronizate.

11

Figura 1.4. Reprezentarea patternurilor MV*
(mvc -mvp-and-mvvm -design -pattern)

1.3.Navigarea în SPA

Într-o aplicație web tradițională, naviga rea este gândită în termeni de pagini web
complete. Când este introdusă o nouă adresă URL în bara de locație a unui browser, de obicei
este trimisă o solicitare pentru pagină din browser către un server, care răspunde prin
trimiterea unei pagini HTML întregi . Ceea ce este trimis înapoi este documentul HTML
pentr u pagina solicitată. După ce HTML -ul pentru acea pagină este primit, browser -ul
primește apoi orice alte fișiere sursă la care se referă doc umentul, cum ar fi orice fișier CSS și
JavaScript. Pentru a afișa noul conținut, browserul efectuează o reîmprospăta re completă.

Figura 1.5. Navigarea într -o pagină web tradițională
(Emmit A. Scott J. , 2016, p. 86)

12

DOM -ul unei aplicații SPA începe, de obicei, ca un prim strat în pagina index, urmând
ca modulele SPA și frameworkul MV*, inclusiv bibliotecile de sprijin, să fie ori descărcate cu
pagina index ori încărcate asincron dacă se folosește o bibliotecă de încărcare de script -uri
AMD. SPA are, de asemenea, capacitatea de a prelua în mod asincron datele și orice șablon
sau alte resurse care nu sunt deja incluse pentru a face view -urile dinamice dupa cum este
necesar.
Pe măsură ce utilizatorul navighează, view -urile sunt afișate fără probleme. Acest
lucru, combinat cu preluarea asincronă a datelor, conferă o experiență extraordin ară pentru
utilizatori. Nu mai există întreruperi întâmpinate în momentul în care o pagină este curățată și
o pagină nouă este încărcată și afișată, aplicația SPA făcând toate acestea fără a reîmprospăta
pagina inițială după ce este încărcată.

Figura 1.6. Navigarea într -o aplicație SPA
(Emmit A. Scott J. , 2016, p. 87)

Întrucât SPA este încă o aplicație bazată pe web, utilizatorii se așteaptă să poată utiliza
bara de adrese și butoanele de navigare . Componenta JavaScript care realizează navigarea în
acest mediu, cu o singură pagină posibilă , se numește router , acesta având rolul de a
determina când este necesară o schimbare a stării prin diferite metode de detectare a
modificărilor în locația browser -ului, cum ar fi ascul tarea de evenimente. Ori de câte ori apare
o modificare a adresei URL , router -ul încearcă să potrivească o parte din noua adresă URL cu
o intrare din configurația sa.
Indiferent de routerul folosit, trebuie să existe o configurație încă de la început în
fișierul de configurare a routerului pentru a face posibilă schimbarea modului în care routerul

13
răspunde/reacționează în timp c e utilizatorul navighează. Fiecare intrare în configurația
routerului este denumită traseu ( route ), acesta fiind stocat la moment ul dezvoltării.
Deși configurația routerului variază , există anumiți termeni specifici utilizați precum :
 Name – pentru unele routere numele este dat, pentru altele calea serve ște ca
identificator al traseului.
 Verbs – routerele sunt uneori definite cu nume de funcții care se potrivesc cu
verbele HTTP, spre exemplu get() sau put() , însă nu întotdeauna. Altele folosesc
nume mai generice, cum ar fi on(), when() sau route() .
 Path – aceasta configurează routerul care stabilește o legătură între adresa URL și
un handler de rută. Acest lucru permite routerului să stabilească ce acțiuni să
realizeze. De fiecare dată când URL -ul se schimbă, routerul compară noul URL
cu toate căile traseu lui din lista aflată în fișierul de configurare.
 Functionality – reprezintă codul asociat care poate fi executat, cum ar fi un
controler sau o funcție de apel invers. Pentru ca traseul să facă ceva, este nevoie de
un cod asociat care să ruleze.
 View – cel mai adesea atunci când un router permite includerea unui view ca parte
din configurația traseului acesta este calea către un parțial HTML.

1.4. Comunicare cu serverul în SPA

Pentru ca o aplicație SPA ce rulează în browser să comunice cu un server, ambele au
nevoie să vorbească aceeași limbă, primul pas ce trebuie făcut fiind acela de a se decide
asupra aceluiași tip de date care vor fi trimise și primite. Existența unui acord între client și
server privind tipul de date și metodele HTTP este esențială pentru ca un apel să aibă succes.
JSON este utilizat în mod obișnuit de SPA atunci când comunică cu servere, d eși tipul de date
poate fi oricare , de la text simplu, până la XML sa u un fișier.
Atunci când un client face o cerere, acesta poate indica tipul de acțiune pe care ar dori
ca server ul să o efectueze prin specificarea metodei solicitate . Pentru ca cererea să aibă
succes, totuși, metoda HTTP specificată în cerere trebuie să f ie acceptată de codul de pe
server pentru acel apel. Dacă nu este, serverul poate răspunde cu un cod de stare 405 Method
Not Allowed.
Deoarece metoda HTTP descrie ce ar trebui să se întâmple cu resursa reprezentată în
cerere, se numește adesea verbul apelu lui. O metodă care nu modifică o resursă, cum ar fi

14
GET, este considerată sigură. Orice metodă care se termină cu același rezultat, indiferent de
câte ori se execută apelul său, este considerată idempotent ă.
Metodele utilizate în mod obișnuit într -o aplica ție SPA sunt :
 GET – În mod obișnuit, este folosit pentru a prelua date.
 POST – Această metodă este utilizată cel mai frecvent pentru crearea unei resurse sau
adăugarea unui element la o resursă.
 PUT – În mod obișnuit, este folosit ă ca o acțiune de actualizare sau de creare, actualizând
resursa existentă sau opțional adăugând -o dacă nu există.
 DELETE – Această metodă este folosită pentru a elimina o resursă.
În multe aplicații SPA, servicii le REST (Representational State Transfer ) sunt extrem
de întâlnite . REST nu este un protocol sau o specificație, ci un stil arhitectural pentru
sistemele hipermedia distribuite, acesta câștigând o popularitate extrem de răspândită. Multe
frameworkuri MV* nu numai că oferă suport pentru acesta, ci și preferă acest stil in mod
implicit.
Într-un serviciu REST, API -urile definesc tipurile de medii care reprezintă resursele și
starea aplicației. URL -ul și metoda HTTP folosită în API definesc regulile de procesare
pentru un anumit tip de suport. Metoda HTTP descrie ce se face, iar adresa URL identifică în
mod unic resursa afectată de acțiune. Unul dintre conceptele fundamentale d in REST este că
totul este o resursă. O resursă este reprezentată de un tip și harte conceptual e către o entitate
sau un set de entități. O resursă ar putea fi un document, o imagine sau o informație care
reprezintă un obiect cum ar fi o persoană.
Fiecare resursă dintr -un serviciu REST trebuie să aibă o adresă URL unică pentru a o
identifica. Aceasta implică adesea crearea și atribuirea de identific atori unici resursei. În
majoritatea cazurilor se dorește asigurarea că orice ID utilizat într-o adresă URL nu afectează
în niciun fel securitatea sau integritatea aplicației. O măsură comună de securitate este aceea
de a atribui un ID generat aleatoriu pentru orice resursă care este personală sau confidențială.
Pentru a se asigura că ID -ul este utilizat numai de către utilizatorul intenționat, codul de pe
server se asigură că solicitantul este utilizatorul autentificat atribuit resursei și are autorizația
corespunzătoare pentru a efectua acțiunea asupra resurselor.
Frameworkurile MV* ajută la consumarea serviciil or REST prin facilitarea trimiterii
metodei corecte HTTP. De obicei, acestea fie au funcții pentru GET, POST, PUT și DELETE fie
permit gererarea fără efort a acestora din configurație.

15
CAPITOLUL 2
TYPESCRIPT ÎN ANGULA R

2.1. Limbajul TypeScript

Peisajul JavaScript include multe limbaje care au drept punct comun codul JavaScript.
Există limbaje dinamic e precum : ES2015(JavaScript), CoffeeScript, ClosureScript și limbaje
strongly typed precum : TypeScript sau Dart sau strongly typed and functional precum Elm
sau PureScript .
TypeScript reprezintă un superset al JavaScript, unul dintre cele mai populare limbaje,
fiind, totodată, utilizat activ în dezvoltarea librăriilor Angular sau a altor librării. Limbaj
strongly typed , TypeScript, este extrem de util deoarece ajută la eliminarea a clase întregi de
buguri care, altfel, ar putea fi detectate doar la runtime . Aceste tipuri de limbaje aduc cu ele
un efort de scriere deoarece trebuie specificate tipurile de clase, de variabile și de semnături
pentru funcți i, dar, în același timp, ele pot ajuta în procesul de documentare, deoarece implică
o remodelare mai facilă a codului. Valoarea acestei investiții va cre ște doar în măsura în care
codul crește. (Suciu)

2.1.1. Tipuri de bază

Tipurile de bază includ tipuri primitive, cum ar fi numărul, șirul, booleanul și matricea
în TypeScr ipt. JavaScript validează tipurile numai în timpul r ulării , dar TypeScript validează
tipurile de variabile în timpul procesului de compilare și reduce foart e mult posibilitatea
apariției problemelor de tip cast pe parcursul rulării .
 Number . Tipul număr reprezintă valori în virgulă mobilă. Poate deține valori cum ar fi
zecimale, binare, hexazecimal și literale octale.
let decimal: number = 6;
let hex: number = 0xf00d;
let binary: number = 0b1010;
let octal: number = 0o744;

 Boolean . Tipul boolean este un tip foarte simplu care poate să dețină una din cele două
valori, adevărat sau fals . Acest tip boolean este folosit pentru a menține starea într -o
variabilă. Variabilei isSaved de tip Boolean îi este atribuită valoarea true.
let isSaved: Boolean;
isSaved = true;

16

 String . Tipul de date string poate conține o secvență de caractere. Declararea și
inițializarea variabilei șir e ste foarte simplă, după cum urmează :
var authorName: string = " Ray Adams ";

 Array. Tipul de date array este menit să dețină o colecție de valori de tipuri specifice.
În TypeScript, putem defini matricele în două moduri, care sunt după cum urmează:
var even:number[] = [2, 4, 6, 8, 10];
Această modalitate declară o variabilă matrice de tipul număr utilizând
paranteze pătrate ([ ]). Al doilea mod de a defini matricea este după cum urmează :
var even:Array< number> = [2, 4, 6, 8, 10];
Această instrucțiune utilizează tipul generic de matrice, care folosește cuvântul
cheie Array, urm at de paranteze unghiulare (< >).

 Enum. Tipul de date enum este utilizat pentru a oferi nume , ușor de manipulat,
constantelor care identifică anumite valori.
enum Day {Mon, Tue, Wed, Thu, Fri, Sat, Sun};
var firstDay: Day = Day.Mon;

 Any. Tipul de date any este un tip de date dinamic care poate deține orice valoare.
TypeScript aruncă erori de compilare dacă este atribuită o variabilă de tip șir unei
variabile întregi. Dacă nu se cunoaște sigur ce valoare va avea o variabilă și se dorește
să se renunțe la ve rificarea compilatorului pentru tipul din atribuire, se poate utiliza
tipul de date any. Aici este f olosit ă o matrice de tipul any , astfel încât să poată deține
orice tip, cum ar fi numere, șiruri de caractere și booleani.
var mixedList:any[] = [ 1, "I am string", false];
mixedList [2] = "no you are not";

 Void. Void este de fapt nimic. Acesta poate fi folosit ca tip de returnare a unei funcții
pentru a declara că această funcție nu va returna nici o valoare:
function alertMessage(): v oid {
alert("This function does not return any value");
}

17
2.1.2. Funcții și tipurile func țiilor

Funcțiile reprezintă cea mai comună sursă de erori în cadrul acestui limbaj. O funcție
obișnuită în TypeScript arată astfel :
function stringToArray(char) {
return char.split(' ')
}
În acest exemplu nu se poate asigura faptul ca char va fi chiar un character, acesta
putând să aiba drept valoare un număr sau orice alt tip. De aceea este nevoie de strictețe în
ceea ce prive ște tipurile valorilor în TypeScript. Funcțiile folosesc tipuri în două părți diferite
ale declarației :
 Parametrii func ției
Se pot transmite către TypeScript tipurile de valori pe care o funcție trebuie să le
primească, iar aceasta va respecta cu strictețe aceste tipuri. Următorul exemplu arată o funcție
care primește un șir tastat și un număr ca parametri:
// Typed parameters
function stringIndex(char: string, index: number) {
const arr = char.split(' ')
return arr[number];
}
Parametrii char și index au tipurile string și respectiv number corect setate. Chiar
înainte ca datele să ajungă la browser, TypeScript va avertiza în cazul în care există ceva în
neregulă.
Desigur, expresiile funcții nu sunt lăsate la o parte :
const stringIndex = function (char: string, index: number) {
const arr = char.split(' ')
return arr[number];
}
Mai mult decât atât, funcțiile de tip arrow sunt binevenite:
const stringIndex = (char: string, index: number) => char.split('')[number];
 Valoarea retunată a funcției.
Valoarea returnată de o funcție atunci când este executată poate fi, de asemenea,
strict ly typed :
function stringIndex(char: string, index: number): string {
const arr = char.split(' ')
return arr[number];
}

18
2.1.2. Interfețe

Intefețele sunt contracte pe care codul trebuie să le respecte, un acord de care
structurile de date trebuie să țină seama, validând, de asemenea, tipurile și disponibilitatea
valorilor trecute. În TypeScript, interfețele sunt utilizate pentru următoarele:
 Crearea de tipuri de obiecte JavaScript.
TypeScript utilizează interfețe pentru a le face mai ușor de între ținut și ușor de înțeles.
Următorul exemplu constă în modul în care scriem interfețe în TypeScript:
interface OptionBag {
show: boolean,
container: string
}
Această interfață poate fi folosită pent ru a crea o variabilă options de tipul OptionBag :
// Typed object
let options: OptionBag = {show: true, container: '#main'};
 Configurarea contractelor pe care clasele le vor respecta .
Se poate asigura faptul că o clasă aderă la un anumit contract utilizând interefețe. Se
folosește termenul de contract în sensul că toate proprietățile și metodele definite în interfață
trebuie implementate în clasă. Fie interfața Note:
interface Note {
wordCount: number
}
Pentru a implementa interfața utilizând o clasă, adăugăm cuvântul cheie implements
după numele clasei urmat de interfața pe care o implementăm:
class NoteTaker implements Note {
// Implement ează wordCount din interfața Note
wordCount: number;
constructor(count: number) {
this.wordCount = count
}
}
Un lucru despre interfețe, totuși, este că proprietățile/metodele definite ale unei
interfețe trebuie furnizate atunci când se creează valorile care sunt tipiz ate cu acea interfață.
Practic, trebuie să se adere strict la contractul stabilit cu o interfață.
O altă situație tipică est e atunci când există proprietăți la care se intențion ează să se
atribui e valori doar o singură dată, la fel ca și cu cuvântul cheie de declarație ES6 const .
Aceste valori pot fi marcate ca readonly .

19
2.1.3. Decoratori

Caracteristica cea ma i comună introdus ă în Angular 2+ este decoratorii. Decoratorii, la
prima vedere, confundă din cauza semnului neobișnui t @ care precede utilizarea lor.
Un membru decorat în mod obișnuit este clasa. De fapt, în Angular, aproape toate
clasele (componente, servicii, module, filtre ș i directive) sunt decorate. Aces ta este motivul
pentru care trebuie înțeleasă importanța existenței decoratorilor. Decoratorii pot fi utilizați
pentru a extinde caracteristicile unei clase, așa cum se arată în următorul exemplu:
// decorator functi on
function config(target) {
target.options = {
id: '#main',
show: true
}
}
// class
@config
class App {}
// options added
console.log(App.options) // {id: '#main', show: true}

Fabricile de decoratori sunt funcții care retu rnează un decorator, oferind puterea de a
trece argumentele pentru decorator prin intermediul fabricii sale:
// decorator factory function
function config(options) {
// decorator function
return function(target) {
target.options = options
}
}
// class decorator
// with arguments
@config({id: '#main', show: true})
class App {}
// options added
console.log(App.options) // {id: '#main', show: true}

20
2.2. Compoziția componentelor în TypeScript

O componentă este o clasă decorată cu un șablon, tipul d ecoratorului fiind cel care
contează, în acest caz decoratorul Component , reprezentând nucleul proiectelor Angular. O
componentă Angular scrisă în TypeScript app.component.ts arată astfel :
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent { title = 'app'; }
Primul pas este acela de a importa decoratorul din modulul Angular @angular/core .
După aceea decoratorul este plasat ch iar lângă clasa AppComponent. Decoratorul primeș te un
obiect JavaScript ca argument pentru a descrie componenta. Acest obiect conține : selector,
templateUrl și styleUrls .
Componentele scrise cu TypeScript sunt cele mai bune atunci când se păstrează scurte
și simple. Totuși, cu componente scurt e și simpl e va fi dificil de realizat o aplicație complexă,
de aceea se va realiza o combinare a acestora pentru atingerea unui anumit task si construirea
unei aplicații utilizabile . Compozabilitatea este cea mai remarcabilă caracteristică a
componentelor. De fapt, acest lucru face ca componentele să fie ceea ce sunt. Nu numai pe
web, ci ori de câte ori o entitate este menționată ca o componentă, atunci are tendința de a fi
compusă cu alte componente. În timp ce unele componente pot funcționa pe cont propriu, cele
mai multe depind în mod implicit sau explicit de alte componente independente pentru a
realiza o anumită sarcină. TypeScript și șabloanele simplifică foarte mult compoziția în
Angular, permițându -i să pună piesele aplicației împreună într -un mod perfect și ușor de
întreținut.
Compoziția se întâmplă ierarhic; prin urmare, majoritatea relațiilor dintre componente
sunt fie părinte -copil sau copil -părinte. De asemenea, este important de reținut că, dac ă există
o astfel de relație părinte -copil, atunci unele componente ar putea fi frații altora, în funcție de
arhitectură. O componentă compusă are o relație parentală cu o altă componentă, fie ca
părinte, fie ca un copil. Există o tendință pentru un lanț i mbricat; prin urmare, nimic nu
oprește o componentă a copilului de a avea un bunic sau o componentă părinte să aibă o
componentă nepoată . Figura 2.1. ilustrează acest lucru mai bine.

21

Figura 2.1. Ierarhia Componentelor (Nwamba, 2017)
Aici, componenta de intrare App are două componente copil : CommentList și
CommentForm . CommentList are, de asemenea, un copil CommentItem . Este în regulă de spus
faptul că CommentItem este nepotul componentei App și că CommentForm și CommentList sunt
frați.

2.3. Client -side Routing pentru aplicații SPA

Aplicațiile pentru o singură pagină (SPA) reprezintă un termen utilizat pentru a se
referi la aplicațiile care sunt difuzate dintr -un singur traseu de server, dar au mai multe
vizualizări ale clienților. Traseul cu un singur server este de obicei implicit (/ sau *). Odată ce
este încărcat ă ruta cu un singur se rver, clientul (JavaScript) deturnează pagina și începe să
controleze ruta utilizând mecanismele de rutare ale browserului.
Capabilitatea de a controla rutele din JavaScript oferă dezvoltatorilor posibilitatea de a
construi experiențe mai bune pentru utili zatori. Acest capitol descrie modul în care acest lucru
se poate face în modulul Angular utilizând clase TypeScriptwritten , directive și așa mai
departe.

22
2.3.1. RouterModel

Pentru ca rutarea să funcționeze, trebuie importat modulul care va fi folosit :
import { RouterModule } from '@angular/router';
Modulul expune o metodă statică forRoot , care este trecut ă într-o serie de rute. În
acest scop, se înregistrează și se configurează acele rute pentru modulul care importă
RouterModule . Se începe cu crearea un ui fișier routes.ts în dosarul app:
import { Routes } from '@angular/router';
export const routes: Routes = [
{path: '',
component: HomeComponent },
{path: 'about',
component: AboutComponent },
{path: 'contact',
component: ContactComponent }
];
Semnatura clasei Routes este o matrice care ia unul sau mai multe obiecte. Obiectul
care este transmis trebuie să aibă o cale și o proprietate a componentei. Proprietatea căii
definește locația în timp ce proprietatea componentei definește compone nta Angular care ar
trebui montată pe calea definită. Apoi, poate fi configurat RouterModule cu aceste matrici în
AppModule . RouterModule a fost deja importat, așa ca următorul pas constă în importarea
fișierelor de rute și configurarea rutelor în matricea importurilor , acestea fiind tot ce este
nevoie pentru configurarea traseelor în Angular :
import { BrowserModule } from '@angular/platform -browser';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { AppCompo nent } from './app.component';
import { routes } from './routes';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
RouterModule.forRoot(routes) ],
providers: [],
bootstrap: [AppComponent]})
export class AppModule { }

23
2.3.2 Router Directives

Angular expune două directive importante de rutare :
 Router outlet : Aceast ă directivă definește locul în care trebuie montat ă configurația
rutei. Aceasta este, de obicei, într -o componentă de intrare pentru apli cațiile SPA.
 Router link : Aceasta directive este utilizată pentru a defini navigația pentru rutele
Angular . Practic, adaugă caracteristici etichetei anchor , astfel încât să funcționeze mai
bine cu rutele definite într -o aplicație Angular.
După încheierea fiecărui ciclu de viață de navigație cu succes, routerul construiește un
arbore al obiectelor ActivatedRoute care alcătuiesc starea curentă a routerului. Actualul
RouterState poate fi accesat de oriunde din aplicație utilizând serviciul Router și proprietatea
routerState .Fiecare ActivatedRoute din RouterState oferă metode pentru a traversa în sus și
în jos în arborele de traseu pentru a obține informații de la rutele părinte, copil și frate. Calea
traseului și parametrii sunt disponibili pri ntr-un serviciu de router injectat numit
ActivatedRoute ce conține o mulțime de informații utile , precum :
 url: Un Observable a căii traseului, reprezentată ca o matrice de stringuri pentru fiecare
parte a căii traseului.
 data: Un Observable care conține obiecte data furnizate pentru traseu. De asemenea
conține orice valoare furnizată de resolve guard .
 paramMap : Un Observable care conține o hartă a parametrilor necesari și opționali specifici
rutei. Harta acceptă extragerea valorilor unice și multiple de la același parametru.
 queryParamMap : Un Observable care conține o hartă a parametrilor de interogare
dispon ibili pentru toate rutele. Harta acceptă extragerea valorilor unice și multiple din
parametrul int erogării.
 fragment : Un Observable al fragmentului URL disponibil pentru toate rutele.
 outlet: Numele al RouterOutlet folosit pentru afișarea rutelor.
 routeConfig : Configurația rutei utilizată pentru ruta care conține calea de origine.
 parent : Părintele routerului ActivatedRoute atunci când acest route este un route copil.
 firstChild : Conține primul ActivatedRoute din lista rutelor copil.
 children : Conține toate rutele copil activate sub routerul curent. . (angular.io)

24
CAPITOLUL 3
ANGULAR -CONCEPTE DE BAZĂ

3.1. Arhitectura unei aplicatii Angular

Angular este o platformă și un framework pentru crearea de aplicații client în HTML
și TypeScript care face aplicațiile web mai ușor de construit . Angularul însuși este scris in
limbajul TypeScript . Acesta combină șabloanele declarative, injectarea de dependență și cele
mai bune practici integrate pentru a rezolva provocările de dezvoltare , împuterni cind
dezvoltatorii să construiască apli cații care să trăiască pe web, pe mobil sau pe desktop .
Blocurile de bază ale unei aplicații Angular sunt NgModules , care oferă un context de
compilare pentru componente. NgModulele colectează codul asociat în seturi funcționale; o
aplicație Angular este definită de un set de NgModules . O aplicație are întotdeauna cel puțin un
modul rădăcină care per mite bootstrapping și de obicei, pe lângă acesta, mai are multe alte
module.(angular.io)
Arhitectura Angular cuprinde module, c omponente, șabloane, metadate, directive și
servicii. (Figura. 3.1)

Figura 3.1. Arhitectura Angular
(Mathieu Nayrolles Rajesh Gunasundaram Sridhar Rao, July 2017)

25

Angular are mai multe tipuri de entități de nivel superior cu roluri specifice și
capabilități folosite în diverse combinații pentru a crea aplicația dorită :
 Module – Obiecte care ajută la organi zarea dependențelor în unități discrete .
 Componente – Noi elemente care vor compune majoritatea structurii și logicii aplicației .
 Directive – Obiecte care modifică elementele pentru a le oferi noi capacități sau pentru a
le schimba comportamentele .
 Pipe – Funcții care formatează date înainte ca acestea să fie redate .
 Servicii – obiecte reutilizabile care completează roluri de nișă, cum ar fi accesul la date
sau utilitarele auxiliare .
O clasă poate fi transformată într -o componentă prin adnotarea acesteia cu @Component
și prin transmiterea metadatelor necesare, cum ar fi selector, template sau templateUrl.
Angular consideră o clasă ca o componentă numai după atașarea metadatelor la acea sta.

Figura 3.2. Atașarea metadatelor la o componentă
(Mathieu Nayrolles Rajesh Gunasundaram Sridhar Rao, July 2017)

26
O componentă este o clasă care are proprietăți și metode pentru a fi folosite în view.
Aceste proprietăți și metode permit view -ului să interacționeze cu componentele . Ciclul de
viață al unei componente este gestionat de Angular în funcție de interacțiunile utilizatorului cu
aplicația. De as emenea, putem adăuga o metodă eveniment care va fi lansată în funcție de
schimbările de stare al e componentei. Aceste metode eveniment sunt cunoscute sub numele
de life cycle hooks și sunt opționale.
Șabloanele pot fi considerate ca o reprezentare a unei componente care este
vizualizată în funcție de nevoile UI / UX ale unei aplicații. O componen tă va avea un șablon
asociat acesteia . Șablonul este responsabil pentru afișarea și actualizarea datelor în funcție de
evenimentele utilizatorilor .
Un decorator furnizat de TypeScript este o funcție care ia parametrii de configurare
folosiți de Angular pentru a crea o instanță a componentei și pentru a reda vi ew-ul asociat .
Parametrii de configurare pot avea, de asemenea, informații despre directive și furnizori, care
vor fi puse la dispoziție de Angular atunci când compon enta este creată.
Conceptul de Data Binding (legarea datelor) reprezintă una dintre responsabilitățile
principale ale dezvoltatorilor atunci cand scriu cod , acesta fiind utilizat pentru a lega datele cu
interfața și pentru a actualiza modificarea datelor în funcție de interacțiunile utilizatorilor cu
interfața. Angular a redus enorm sarcina de a scrie cantități mari de cod pentru a manipula
legarea datelor prin coordonarea cu șabloanele si componentele. Șabloanele oferă instrucțiuni
lui Angular despre cum și ce să lege.

Figura 3.3. Conceptul de property binding în Angular
(Mathieu Nayrolles Rajesh Gunasundaram Sridhar Rao, July 2017)

27
Există două tipuri de binding : One-way Data Binding și Two-way Data Bingind . Cea
dintâi se referă la legarea datelor într -o singură direcție, fie de la componentă la DOM, fie de
la DOM la componentă, în timp ce cealaltă se ocupă de ambele părți ale comunicării, adică de
la componenta la DOM și invers.
O directivă este o instrucțiune sau un g hid pentru redarea unu i șablon. O clasă
decorată cu @Directive pentru metadatele atașate se numește directivă. Există trei tipuri de
directive susținute de Angular: directiva privind componentele, directiva structurală și
directiva privind atributele .
O componentă este o formă a unei directive cu un șablon care este decorat cu
@Component : este de fapt o extensie @Directive cu un șablon. Directivele structurale
manipulează elementele DOM și modifică structura lor prin adăugarea, eliminarea și
înlocuirea elementelor DOM. O directivă atribut ajută la actualizarea comportamentului sau a
aspectului unui element.
Serviciile sunt clase definite de utiliza tor folosite pentru rezolvarea problemelor.
Angular recomandă numai coduri specifice șablonului în componente. Responsabilitatea unei
componente este îmbogățirea UI / UX în aplicația Angular și deleghează servicii le să se ocupe
de logica aplicației . Compon entele sunt deci consumatori de servicii .
Logica specifică aplicației, cum ar fi persistența datelor , erorile de înregistrare și
stocarea fișierelor ar trebui să fie delegate la servicii, iar componentele ar trebui să consume
respectivele servicii care se ocupă de logica corespunzătoare a aplicației.
Atunci când se creează o instanță a unei clase, furnizarea dependențelor necesare ale
acelei clase pentru ca aceasta să funcționeze corect, s e numește Dependency Injection ,
Angular oferind o versiune modernă și îmbunătățită a acestui pattern .

Figura 3. 4. Dependency Injection
(Mathieu Nayrolles Rajesh Gunasundaram Sridhar Rao, July 2017)

28
Componentele au logica legată de șabloane și consumă în cea mai mare parte servicii
pentru a realiza logica aplicației. Așadar, componentele depind de servicii. Atunci când este
scris codul pentru componente, este creat un constructor cu parametrii care preia serviciul ca
argument. Aceasta înseamnă că crearea unei instanțe a componentei d epinde de parametrul
serviciului din constructor. Angular cere ca injectorul să furnizeze instanța serviciului în
parametrul constructorului componentei. Injectorul va servi instanța serviciului solicitat, dacă
ese disponibil, altfel, creează unul nou și î l servește.
Partajarea datelor de la o componentă la alta formează un asp ect important al
aplicației, Angular permițând multe moduri în care poate fi realiza tă această funcționalitate de
partajare a datelor , fie prin utilizarea serviciilor sau a oricăror a ltor biblioteci javascript
externe.
Un serviciu este, în principiu, o funcție care poate ef ectua o singură funcționalitate ce
trebuie implementată în mod frecvent în cadrul mai multor module, ceea ce face în principiu
un cod reutilizabil și care reduce dup licitatea codului.
Serviciile pot fi utilizate cel mai bine pentru crearea, ac tualizarea și ștergerea
datelor,u nul dintre scopurile principale ale utilizării serviciilor în Angular fiind aplicarea
principiului de separare a preocupărilor.

Figura 3. 5. Partajarea datelor prin utilizarea serviciilor
(angular -framework -introduction)

29

3.2. Module

Angular este compus din mai mu lte module, iar orice bibliotecă externă va fi de
asemenea împachetată în alte module. Există două tipuri de module în Angular, module
JavaScript (module specifice adăugate limbajului în ES2015 și nu alte module system ca
CommonJS și AMD) și module Angular.
Modulele JavaScript sunt o modalitate de a separa codul în diferite fișiere care pot fi
încărcate după cum este necesar, dar ele nu sunt module Angular. În timp ce modulele
JavaScript sunt contrucții ale limbajului , modulele Angular sunt construcții logice utilizate
pentru organizarea unor grupuri similare de entități ( cu m ar fi toate lucrurile necesare pentru
router) și sunt utilizate pentru a înțelege ce trebuie încărcat, precum și ce dependențe există.
Un modul este declarat prin crearea unei clase și decorarea acesteia cu decoratorul
@NgModule .
@NgModule({
declaration s: [
AppComponent,
SummaryComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule
],
providers: [StocksService],
bootstrap: [AppComponent]
})
export class AppModule { }

Această declar ație a modulului furnizează părț i cheie de informație lui Angular astfel
încât poate înțelege cum este afișată și încărcată aplicația. Decoratorul @NgModule conține
metadatele pentru modulul App și clasa goală acționează ca loc pentru stocarea datelor.
Matricea declarations conține o li stă a tutu ror componentelor și directivelor pe care
modulul principal al aplicației dorește să le pună la dispoziția întregii aplicații. De asemenea,
matricea providers conțin e o listă a tuturor serviciilor care vor fi puse la dispoziția întregii
aplicații . Matricea imports conține o listă a celorlalte module de care depinde acest modul.
Dacă există probleme cu un alt modul care nu se încarcă, acesta este primul loc pentru a

30
verifica dacă este înregistrat . Pentru a începe redarea, Angular trebuie, de asemenea, să știe ce
componentă sau componente trebuie să redea pe ecran și va căuta în matricea de bootstrap
pentru a știi ce anume să listeze . Aproape întotdeauna, aceasta va conține doar o componentă,
dar în unele cazuri rare est e posibil să fie necesar să se redea mai multe componente la
încărcare.

3.3. Componente

O componentă este un element încapsulat care își păstrează propria logică internă
pentru modul în care dorește să afișeze unele rezultate. În HT ML, un element select poate fi
considerat o componentă. Folosind Angular , devine posibilă crearea propriile elemente
HTML folosind componente, deși acestea reprezintă mai mult decât atât. Componentele pot
avea orice număr de însușiri sau proprietăți care sunt ulterior definite .
Există câteva principii cheie care se concentrează pe modul în care componentele sunt
cel mai bine proiectate și pe modul în care acestea se comportă în Angular :
 Encapsulation – Păstrează logica componentelor izolată
 Isolation – Păstrează componentele interne ascunse
 Reusability – Permite reutilizarea componentelor cu efort minim
 Event -based – Emite evenimente în timpul ciclului de viață a unei componente
 Customizable – Posibilitatea de a stiliza și exitinde componenta

3.3.1. Comunicarea între componenta părinte și componenta copil

Componentele reprezintă blocurile ce construiesc o aplicați ei Angular și orice astfel de
aplicație are nevoie de cel puțin o componentă numită componentă rădăcină care trebuie
definită îna inte ca aceasta să poată fi executată.
import { Component } from '@angular/core';
@Component({
selector: 'my -app',
template: `
<div class="container text -center">
<div class="page -header">
<h1>{{title}}</h1>
</div>
<p class="lead">{{description}}</p>
</div>
</div>

31
<div class="row">
<div class="col -md-6">
<p>A child component could go here</p>
</div>
<div class="col -md-6">
<p>Another child component could go here</p>
</div>
</div>
</div>`
})
export class AppComponent {
title: string;
description: string;
constructor(){
this.title = ‘The story – Chapter 4’;
this.description = 'This is short story about a girl.';
}
}
În timp ce o componentă rădăcină r eprezintă containerul pentru o aplicație Angular, va
fi nevoie și de alte componente care sunt descendenți direcți sau indirecți ai unei componente
rădăcină. Atunci când o componentă rădăcină este redată, ea va reda, de asemenea, toate
componentele sale copil. Aceste componente copil pot primi date de la componenta părinte și
pot trimite date înapoi către aceasta; o astfel de componentă poate fi definită astfel :
import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'div[my-child-comp]',
template: `
<p>{{myText}}</p>
<button class="btn btn -default" type="button" (click)="onClick()">Send
message</button>`
})
export class ChildComponent {
private static instanceCount: number = 0;
instanceId: number;
@Input() myText: string;
@Output() onChildMessage = new EventEmitter<string>();
constructor(){
ChildComponent.instanceCount += 1;
this.instanceId = ChildComponent.instanceCount;

32
}
onClick(){
this.onChildMessage.emit(`Hello from ChildComponent with instance
id: ${this.instanceId}`);
}
}
Decorator ul @Input() ar trebui aplicat la orice proprietate a componentei care poate
primi date de la componenta părinte. Cel de -al doilea decorator @Output() ar trebui să fie
aplicat oricărei proprietăți care poate trimite date componentei părinte. Angular definește o
clasă E ventEmitter care facilitează generarea și consumarea evenimentelor utilizând o
abordare similară cu evenimentele EventEmitter sau jQuery din Node.js. Evenimentul de
ieșire al tipului de date string este generat în metoda onClick(), iar orice componentă păr inte
se poate abona la acest eveniment pentru a primi date de la componenta copil.

Figura 3.6 . Comunicare între component
(communication -between -components -using -input -in-angular)

3.3.2. Ciclul de viață al componentelor

Fiecare componentă furnizată de Angular are propriul său ciclu de viață : este
inițializată, verificată dac ă a suferit schimbări și distrusă ( printre alte evenimente). Angular
oferă metode care sunt disponibile prin interfețe funcționale TypeScript și pot fi opțional
implementate de clasa comp onentă :
 ngOnChanges : Aceast ă metodă este apelată odată ce proprietățile componentei sunt
inițializate sau sunt schimbate , înainte de ngOnInit . Este, de asemenea, parte a

33
ciclului de viață al directivei (convenția este că numele funcției de implementare a
interfeței are prefixul ng adăugat la numele interfeței, de exemplu, ngOnInit și
OnInit ).
 ngOnInit : Este apelată o dată după prim ul ngOnChanges și când proprietățile
componentelor și proprietățile de int rare sunt toate inițializate. De asemenea, face
parte din ciclul de viață al directivei.
 ngDoCheck: Detectează și acționează asupra schimbărilor pe care Angular nu le poate
detecta sau nu le va detecta singur. Este apelată în timpul fiecărei detectări a unei
schimbări, imediat dupa ngOnChanges() și ngOnInit().
 ngAfterContentInit : Se apelează o dată după primul apel ngDoCheck și când șablonul
component ei este complet inițializat.
 ngAfterContentChecked: Se apelează o dată după ngAfterContentInit și după fiecare
apel ngDoCheck , când conținutul componentelor este verificat.
 ngAfterViewInit : Se apelează o dată după primul ngAfterContentChecked și când sunt
inițializate toate vi ew-urile componentelor și view -urile copii lor lor .
 ngAfterViewChecked : Se apelează o dată după ngAfterViewInit și după fiecare apel
ngAfterContentChecked , când toate vi ew-urile componentelor și ale copii lor lor sunt
verificate.
 ngOnDestroy : Se apelează atunci când componenta urmează să fie distrusă și ar trebui
folosită pentru operațiile de curăț are.

3.4. Angular Router

Rutarea este parte integrantă a aplicațiilor frontend de astăzi. În general, u n router
servește două scopuri: face aplicația navigabilă, astfel încât utilizatorii să poată utiliza butonul
de navigare al browserului și să stocheze și să împartă linkuri în cadrul aplicației ; descarcă
părți din componența aplicației, astfel încât r outerul să își asume responsa bilitatea de a
compune cererea pe baza rutelor și a parametrilor de traseu .
Odată cu definirea rutelor sau a căii, navigarea ajută utilizatorii să ajungă la paginile
aplicației, să exploreze funcționalitățile și este, de asemenea, foarte utilă în scopuri
SEO(Search Engine Optimization).
Pe baza unei configurații a routerului, care poate fi plasată în cadrul componentei,
routerul va decide care componente trebuie să fie instanțiate și plasate în outleturile

34
routerului. De asemenea, r outerele pot fi parametrizate, acești parametrii putând fi accesați în
componentele instanțiate.
În funcție de arborele de componente și de configurațiile routerului din componentele
acestui arbore, poate fi construită o rutare ierarhică și routerele compo nentelor copil pot fi
decuplate de pe rutele componentelor părinte. Astfel de rute imbricate fac posibilă
specificarea configurației traseului pe mai multe straturi în arborele de component e și
reutilizarea componentelor părinte pentru mai multe căi copil.

Figura 3.7 . Ierarhia routerului stabilită printr -un arbore de component
(Kunz, 2016)

35

3.4.1. Blocuri importante

Cele mai importante blocuri ce construiesc un router sunt base href , Router Outlet ,
routerLink și routerLinkActive .
 base href : Directiva base trebuie setată în pagina index.html , acesta constituind un pas
obligatoriu. Fără tagul base, nu pot încărca te resursele (imagini, CSS și scripturile). De
obicei , base href este definit în interiorul tagului <head> din pagina index.html: <base
href=”/”> .
 Definirea router-outlet : Această directivă marchează locul unde routerul va afișa view –
ul. În interio rul directive router-outlet , view -urile componentei vor fi încărcate și
afișate, urmând ca aceasta să fie plasată în app.component.html pentru a afișa datele:
<router-outlet></router -outlet>.
 Utilizarea mai multor directive router -outlet : În anumite cazuri, se va dori încărcarea
datelor în diferite view -uri în loc de directiva router-outlet . Se pot adăuga mai multe
astfel de directive într -o pagină și asigna nume fiecăreia, astfel încât datele respective pot
fi încărcate în interiorul lor.
<router-outlet></router -outlet>
<router-outlet name="content -farm"></router -outlet>

Pentru a încărca datele view -ului în interiorul router -outletului denumit, se vor defini
chei în timpul definirii routerului.
{
path: 'content', component: ContentFarmComponent,
outlet: 'content – farm'
}
 RouterLink : Acesta indic ă URL -ul sau adresa link care poate ajunge direct de la bara de
adresă a browserului . Dacă se va face click pe un element cu o astfel de directivă, se va
declanșa automat o navigație .
<a [routerLink] ="['/about']">About Us</a>
<a [routerLink] ="['/product s']">Products</a>
<a [routerLink] ="['/services']">Services</a>
 RouterLinkActive : Directiva pentru adăugarea/ eliminarea claselor dintr -un element
HTML atunci când un routerLink asociat conținut pe sau în inte riorul elementului devine
activ/ inactiv. Este utilizat pentru a evidenția linkul care este activ în momentul curent.
<a [routerLink] ="['/about']" routerLinkActive = "active-state">About Us</a>

36
 Construirea dinamică a routerLink . Pot fi trimise valori dinamice sau parametrii prin
legarea acestora cu directiva routerLink pentru a transmite date personalizate.
<a [routerLink] ="['/product', product.id]">Product 10</a>
 Trimiterea de matrici și seturi de date cu directiva routerLink . Pot fi transmise matrici de
date împreună cu routerLink .
<a [routerLink] ="['/contact s', {customerId: 10}]">Crisis Center</a>

3.4.2 . Route Guards

Gărzile de rută permit controlul asupra diferitelor stadii ale unei navigări. În timp ce
are loc navigarea de la o componentă la alta, trebuie să fie asigurat faptul că datele care vor fi
afișate sunt autorizate pentru utilizator și, în caz contrar, navigarea să fie anulată. Route guard
poate întoarce un obiect Observable <boolean> sau Promise<boolean> , iar router -ul va aștepta
ca Observable să se rezolve fie la adevărat, fie la fals : dac ă retunează adevarat, va continua cu
navigarea și va afișa view -ul; dacă returnează fals, va anula navigarea.
Există diferite route guard care pot fi utilizate fie în mod independent, fie în
combinații. Ele sunt după cum urmează:
 canActivate
 canActivateChild
 canDeactivate
 Resolve
 canLoad

Func ția guard poate accepta parametrii pentru a lua o decizie mai bună. Parametrii
care pot trimiși sunt după cum urmează :
 component : Directivele personalizate ale componentelor care au fost create .
 route : ActivatedRouteSnapshot este viitoarea rută care va fi activată dacă există acces .
 state : RouterStateSnaps hot este starea viitoare a traseului în cazul în care exist ă acces.
 canActivate : Acest parametru protejeaz ă componenta. Trebuie îndeplinite toate criteriile
necesare înainte ca o rută să poată fi activată.
 canActivateChild : Protejează componentele copil, verificând accesul la ruta componentei
copil.
 Funcția canActivateChil d este similară cu canActivate , cu o diferență esențială că
această funcție protejează rutele copilului componentei.

37
 canDeactivate : Aceasta gestionează toate modificările nesalvate din pagină – de multe ori
atunci când un utilizator încearcă să părăsească o pagină care are modificări nesalvate,
acesta trebuie informat despre modificările în așteptare și trebuie să existe, de asemenea, o
confirmare dacă utilizatorul dorește să -și salveze munca sau să continue fără salvare.
 Resolve : Efectuează recuperarea da telor de rută înainte de activarea rutei ; obținerea
datelor de la service înainte ca ruta să fie activată .
 canLoad : Protejează modulul chiar înainte de încărcare – utilizând canActivate ,
utilizatorul neautorizat este redirec ționat către alte pagini de dest inație, dar în aceste cazuri
modulul se încarcă. Poate fi evitată încărcarea modulului folosind funcția canLoad .

3.5. Directive

Directivele permit extinderea comportamentului elementelor prin manipularea DOM –
ului unei pagini HTML folosind diferitele tipuri de directive. Există trei tipuri de directive în
Angular :
 Componente – sunt directive cu un template(șablon).
 Directive structurale – modifică aspectul DOM prin adăugarea și eliminarea elementelor
DOM.
 Directive atribut – directive care extind comportamentul sau aspectul unui element.
Componentele sunt cele mai co mune dintre cele trei directive, fiind definite de către
utilizator în scopul extinderii funcționalității și creării de funcționalități mici, reut ilizabile.
Așa cum reiese și din denumire, directivele structurale sunt responsabile pentru
aspectul HTML. Ele modelează sau remodelează structura DOM, în general prin adăugarea,
eliminar ea sau manipularea elementelor ; sunt afișate cu un simbol(*) asterisc înainte de
denumirea directivei. Ca și în cazul altor directive, o directivă structurală se aplică unui
element gazdă. Directiva face apoi tot ce ar trebui să facă cu elementul gazdă și descendenții
săi. Unele dintre directivele structurale utilizate în m od obișnuit sunt următoarele:
 *ngFor : În general este folosită pentru a itera și a afișa elementele unui obiect.
<ul>
<li *ngFor="let book of books">
{{book.title}}
</li>
</ul>

38
Aici, elementul div are o directivă * ngFor care se iterează prin obiectul de colectare a
cărților și înlocuiește titlul fiecărei cărți.
 *ngIf: Afișează sau ascunde elemente DOM în funcție de rezultatul evaluării expresiei;
rezultatul este fie adevărat, fie fals.
<div *ngIf="!isLoggedIn">
<p>Hello Guest user</p>
</div>
 *ngSwitch : Verifică dacă valoarea expresiei de potrivire se potrivește cu valoarea
expresiei switch . Rezultatul returnat poate fi orice valoare; se face o verificare
condiționată pentru valorile potrivite.
<ul [ngSwitch]= "person" >
<li *ngSwitchCase= "'Dany'">Hello Dany</li>
<li *ngSwitchCase= "'Emily'">Hello Emily</li>
<li *ngSwitchCase= "'Eva'">Hello Eva</li>
<li *ngSwitchDefault> Bye bye</li>
</ul>
Directivele atribut sunt foarte asemănătoare atributelor HTML . O astfel de d irectivă
necesită minim o construcție a unei clase controler adnotată cu @Directive , care specifică
selectorul care identifică atributul. Clasa controlerului implementează comportamentul
directivei dorite. Angular oferă atât directive atribut integrate : ngModel, ngClass, ngStyle ,
cât și posibilitatea de creare a unor directive atribut customizate. Prin crearea de directive
personalizate definite de utilizator, este permisă definirea și extinderea comportamentul ui și
funcționalității elementelor din pagină. Pentru a crea directive personalizate, trebuie folosit
decoratorul @Directive și implementată logica în definiția clasei.
3.6. Pipes

Pipe-urile sunt mici fragmente de cod care transformă valorile datelor pentru ca
acestea să poată fi afișate utilizatorulu i în t emplate într-un format diferit față de formatul în
care sunt stocate . Acestea permit definirea logicii de transformare în clasele autonome, astfe l
încât să poată fi aplicate în mod consecvent în cadrul unei aplicații.
Pipe-urile permit formatarea conținutul șablonului, chiar în șablon. În locul formatării
conținutului în componentă, se poate scrie un pipe pentru a face acest lucru exact în șablon.
Iată un exemplu perfect pentru un pipe :
<div class="container">
<h2>{{0.5 | percent}}</h2>
</div>

39
Decoratorul @Pipe este aplicat unei clase și folosit pentru a -i specifica un nume prin
care pipe-ul poate fi folosit într -un șablon. Sunt adăugate în expresiile din șabloane folosind
caracterul pipe (|). Angular vine cu un set de pipe -uri implicite care ac operă o serie de cazuri
obișnuite de utilizare. Pipe-urile implicite sunt întotdeauna disponibile și nu trebuie să fie
injectate sau importate, astfel încât să poată fi folosi te în șabloane . Acestea sunt utilizate prin
adăugarea caracterului pipe și a nume lui pipe -ului respectiv .

Tabelul 3 .1. Pipe-uri în Angular
Pipe Funcționalitate

LowerCasePipe Tranformă literele dintr – un text în
litere mici.
UpperCasePipe Tranformă literele dintr – un text în
litere mari.
DatePipe Form atează o dată conform
regulilor locale.
CurrencyPipe Formatează un număr ca monedă
folosind regulile locale.
JsonPipe Convertește o valoarea în șir
JSON.
PercentPipe Form ateaz ă un număr ca procent
în conformitate cu regulile locale.
DecimalPipe Form atează un număr ca text.
SlicePipe Creează o nouă listă sau un șir care
conține un subset a elementelor.
AsyncPipe Realizează subscribe la un
Observable sau o Promise și
returnează cea mai recentă valoare
pe care a emis -o.

40
Sintaxa pentru definirea pipe-urilor este similară cu cea utiliz ată pentru definirea
modulelor, directive lor și a componente lor. Pentru a crea o nouă pipe, este utilizat decoratorul
ES2015, @Pipe . Acesta permite adăugarea metadate la o clasă, declarând -o ca o pipe . Tot ce
trebuie făcut este să se furniz eze un nume pentru pipe și să se definească logica formatării
datelor. În timpul execuției, odată ce Angular constată că o expresie dată include o chemare a
unei pipe, ace sta o va extrage din colecția de pipe -uri alocate în componentă și o va invoca cu
argumente adecvate.

3.7. Observable, HttpClient

Modelul Observable permite unui obiect numit subiect(subject) să țină evidența altor
obiecte, numite observator (observable) , interesate de starea subiectului . Atunci când se
schimbă starea subiectului, acesta își notifică observato rii despre acest lucru.
Un observator este în esență un emițător de evenimente asincron care informează un
alt element, numit Observer, faptul că starea s -a schimbat . Pentru a face acest lucru,
Observab el-ul pune în aplicare toate echipamentele de care are nevoie pentru a produce și
emite astfel de evenimente asincronice și poate fi declanșat și anulat în orice moment,
indiferent dacă a emis evenimentele de așteptat deja sau nu.
Acest model permite operații concurente și o logică mai avansată, deoarece
observatorii care subscriu la evenimentele asincrone ale Observable -ului vor reacționa pentru
a reflecta modificarea de stare a observable -ului la care se abonează.
Acești abonați, care sunt observatorii menționați mai devreme, vor continua să asculte
ceea ce se întâmplă în Observab le până când dispare o bservatul, dacă se va întâmpla vreodată
în cele din urmă. Între timp, informațiile vor fi actualizate în întreaga aplicație, fără
intervenția altor rutine de declanșare.
Observable oferă avantaje semnificative față de alte tehnici pentru manipularea
evenimentelor, programarea asincronă și manipularea mai multor valori. Acestea sunt
declarative – adică, dacă este definită o funcție pent ru publicarea valorilor, aceasta nu este
executată până când un consumator nu se abonează la ea. Consumatorul abonat primește
notificări până la finalizarea funcției sau până când se dezabonează.
Angular utilizează Observable ca o interfață pentru a trata o varietate de operații
asincrone astfel : clasa EventEmitter extinde Observable , modulul HTTP folose ște observable
pentru a răspunde solicitărilor și răspunsurilor AJAX, modulele Router și Forms îi utilizează
pentru a asculta și a răspunde la evenimentele de intrare venite de la utilizatori .

41

Figura 3.8 . O abonare simplă a unui observable cu emis ie de valoare si o transformare
(Kunz, 2016)
RxJS este o bibliotecă pentru compunerea codului asincron și callback -ului într -un stil
funcțional, reactiv. Multe API -uri Angular , inclusiv HttpClient , pro duc și consumă RxJS
Observables .
Cele mai multe aplicații de tip front -end comunică cu serviciile backend prin
intermediul protocolului HTTP. Browserele moderne acceptă două API -uri diferite pentru a
face cereri HTTP: interfața XMLHttpRequest și API fetch ().
HttpClient în @angular/common /http oferă un API HTTP client simpl ificat pentru
aplicații Angular care se bazează pe interfața XMLHttpRequest expusă de browsere. Printre
avantajele suplimentare ale HttpClient se numără caracteristicile de testare, obiectele de
solicitare și de răspuns tipizate, interceptarea cererilor și a răspunsurilor, observab le apis și
manipularea erorilor. Înainte de a putea utiliza serviciul HttpClient , trebuie importat modulul
Angular HttpClientModule , cele mai multe aplic ații făcând -o în rădăcina AppModule .
(https://angular.io/guide/http )

42
Cererile HTTP asincrone sunt cererile HTTP trimise de browser în numele aplicației.
Termenul asincron se referă la faptul că aplicația continuă să funcționeze în timp ce browserul
așteaptă ca serverul să răspundă. Solicitările asincrone HTTP permit aplicațiilor Angular să
interacționeze cu serviciile web, astfel încât datele persistente să poată fi încărcate în aplicație,
iar modificările pot fi trimise către server și salvate .
Angula r HttpClient returnează observables în urma apelurile metodelor HTTP, acest
fapt oferind mai multe avantaje față de API -urile HTTP bazate pe promises. Observables nu
modifică răspunsul serverului, așa cum se poate întâmpla uneori în urma apelurilor de tip
promises. În schimb, pot fi utilizați o serie de operatori pentru a transforma valorile după cum
este necesar. Solicitările HTTP sunt anulate prin metoda de dezabonare unsubscribe(), pot fi
configurate pentru a obține actualizări ale evenimentelor și, în cazul celor care eșuează, pot fi
reluate cu ușurință.
Angular oferă posibilitatea de a efectua solicitări asincrone HTTP prin intermediul
clasei Http, care est e definită în modulul @angular/http JavaScript și este furnizată ca
serviciu în modulul HttpModule .

constructor(private http: Http, @Inject(REST_URL) private url: string) { }

Obiectul Http primit prin constructor este folosit pentru a face o cerere HTTP GET în
metoda getData (), după cum urmează:

getData(): Observable<Product[]> {
return this.http.get(this.url).map(response => response.json());
}

Promisiunile sunt un alt concept util asincron disponibil în Angular. Conceptual,
promisiunile implementează un model complet diferit. O promisiune este o valoare care va fi
rezolvată sau respinsă în viitor. Ca modelul Observer , ele pot fi folosite pentru a gestiona
programarea asincronă . Verbositatea Observer permite un lucru pe care Promise nu-l poate
realiza : dezabonare. Principala diferență care poate conduce la o decizie cu privire la alegerea
unuia dintre cele două este abilitatea Observable de a captura multe evenimente asincrone
ulterioare, în timp ce Promise poate gestiona un singur eveniment asincron.

43
3.8. Forme în Angular

Formularele reprezintă baza aplicațiilor fii nd utilizate pentru conectarea la o aplicație,
trimiterea unei solicitări, plasarea unei comenzi, rezervarea unui zbor, programarea unei
întâlniri și efectuarea de nenumărate alte sarcini de intrare a datelor. În dezvoltarea unui
formular, este important ă crearea unei experienț e de introducere de date care să ghideze
utilizatorul eficient prin fluxul de lucru. Dezvoltarea formularelor n ecesită abilități de
proiectare , precum și suportul pentru legarea datelor în două direcții, urmărirea schimbărilor,
valida rea și gestionarea erorilor . (angular.io)
Utilizarea formularelor, în general, constituie o modalitate de colectare a datelor de pe
web pentru a le persista ulterior . Există două modalități de abordare a formelor: formele
template -driven și formele reactive. Nici o abordare nu este considerată mai bună decât
cealaltă; trebuie doar să se aleagă cea mai potrivită pentru un anumit scenariu . Diferența
majoră dintre cele două abordări constă în cine este responsabil și pentru ce :
 În abordarea template -driven , șablonul este responsabil pentru crearea elementelor,
formularelor și setarea regulilor de validare, iar sincronizarea se face cu legarea datelor
bidirecționale
 În abordarea reactive , clasa Component este responsabilă pentru crearea formei, a
elementelor sale și stabilirea validării.

3.8.1. Template -driven forms

În cadrul acestui tip de formulare , logica, validările, controlării și așa mai departe, sunt
scrise în partea de șablon a codului, și anume în codul HTML, fii nd potrivite pentru scenarii
simple. Pentru a le putea folosi trebuie importat în mod explicit {FormsModule} din
@angular/forms în modulul aplicației.
Directiva ngForm este ceea ce face ca form ularele bazate pe șabloane să funcționeze,
dar nu este necesară adăugarea acesteia în mod explicit, deoarece Angular o va adăga
automat. Când este inclus FormsModule , Angular va căuta orice etichetă <form> în șablonul
HTML. Va face acest lucru prin intermediul di rectivei ngForm . Directiva ngForm detectează
automat eticheta <form> și se leagă automat de ea.
Inițial, în inputurile din cadrul formei pot fi introduse orice tip de date. Validarea
datelor este esențială în aplicațiile web, iar Angular pune la dispoziție un sistem extensibil
pentru validarea conținutului din forme, bazat pe abordarea folosită în HTML5 .
Există câteva reguli de validare deja scrise prezentate în tabelul Tabelul 3.2.

44
Tabelul 3.2 . Reguli de validare ale formelor în Angular
Reguli de validare
required care necesită ca valoarea să nu fie goală.
requiredTrue care cere ca valoarea să fie adevărată.
minlength ceea ce spune că valoarea trebuie să aibă o anumită lungime
minimă .
maxlength care spune că valoarea nu poate depăși o anumită lungime .
pattern care forțează valoarea să adere la un model RegEx .
nullValidator care verifică că valoarea nu este null.
compose care este utilizat dacă se dorește compunerea mai multor validatori
într-unul, regula de validare este rezultatul preluării unității tuturor
validatorilor furnizați.

3.8.2. Reactive forms

În cazul form ulare lor reactive există o abordare programatică a modului în care sunt
create elementele și stabilite validările, totul fii nd realizat în clasa Component . Clasele cheie
implicate în această abordare sunt :
 FormGroup , care este o grupare c e conține controale de tip one-to-many;
 FormControl , care reprezintă un element de tip input ;
Atât FormGroup , cât și FormControl moștenesc AbstractControl , care conține multe
proprietăți interesante ce pot fi folosite pentru a afișa interfața cu utilizatorul diferit, pe baza
stării pe care o are un anumit lucru. Următoarea listă conține toate stările posibile :
 controls , o listă de instanțe FormGroup .
 value , un dicționar care rep rezintă o pereche cheie -valoare. Cheia este referința dată la
creare, iar valoarea este ceea ce este introdus în input {:'<referință>',<valoare
introdusă>}.
 dirty , o formă care a fost modificată de către utilizator .
 disable , forma poate fi dezactivată.
 pristine , o formă care nu a fost modificată de utilizator.
 status , o reprezentare sub forma de șir a faptului daca forma este validă sau nu.
 touched , butonul Submit a fost apăsat cel puțin o dată.

45
 untouched , butonul Submit nu a fost încă apăsat.
 enable , un Boolean care spune daca forma este activată.
 valid , are valoarea true daca forma nu conține erori.
 invalid , opusul lui valid .

Tabelul 3 .3. Template driven forms vs. Reactive forms
Template driven forms Reactive forms

Ușor de folosit Mai flexibil, dar are nevoie de
multă practică
Potrivite pentru scenarii simple Gestionează orice scenariu
complex
Two-way-data binding (utilizând sintaxa
[(Ng Model)]) Nu se utilizează data binding
Cod mai puțin la nivelul componentelor Mai mult cod la nivelul
componentelor și mai puțin
HTML
Testarea poate reprezenta o provocare, fiind
mai dificil de realizat Ușor de testat
Urmărirea automată a formularului și a
datelor sale (tratate de Angular) Transformările reactive pot fi
posibile, cum ar fi:
 Manipularea unui eve niment
bazat pe un timp de debounce
 Manipularea evenimentelor
când componentele sunt
distincte până la schimbare
 Adăugarea elementelor
dinamic

46

APLICAȚIE – BALLROOM MANAGEMENT SYSTEM

4.1. Introducere

Aplicația Ballroom Booker este realizată în scopul de a simula adăugarea,
modificarea și eliminarea de restaurante precum și gestionarea detaliilor legate de acestea, în
cadrul ei existând două tipuri de utilizatori : admin și utilizator obișnuit , fiecare dintre aceștia
putân d vizualiza doar partea din aplicație pentru care este autorizat – adminul este cel care
poate efectua operațiile de adaugare, editare, ștergere asupra listei de restaurante , în timp ce
utilizatorului i se oferă posibilitatea de a vizualiza totalitatea restaurantelor existente împreună
cu detaliile legate de acestea (datele de contact, meniurile puse la dispoziție, saloanele ce pot
fi rezervate ), a le f iltra și a trimite o cerere de î nchiriere a unui salon pentru o anumită dată ,
dacă aceasta este valabilă .
Tehnologiile utilizate în realizarea acestei aplicații sunt:
 Angular ( v.4.) – framework JavaScript util în crearea de aplicații single -page (SPA) ;
 Angular Material (v. 5.2.4) – este atât un framework al componentei UI, cât și o
implementare de referință a Google Material Design Specification . Acesta oferă un set de
componente UI reutilizabile, bine testate și accesibile, bazate pe Material Design.
 Servicii REST – Spring MVC Framework;
 Hibernate – framework de tip ORM (Object Relational Mapping) folosit pentru persistența
datelor, deoarece se aplică bazelor de date relaționale (prin intermediul JDBC).
 MySQL Server – utilizat pentru gestionarea bazelor de date rela ționale ;
 HTML – limbaj de marcare folos it pentru realizarea scheletului de prezentare a
informa țiilor paginilor web afișate în browser ;
 CSS – standard pentru formatarea elementelo r dintr -un document HTML;
Partea de front -end a aplicației a fost realizată folosind frameworkul Angular, flexibil
și independent de platforma pe care rulează , acesta implementează eficient conceptul MVC,
pentru interactivitatea paginilor folosindu -se modulul HttpModule ce simplifică acțiunil e
uzuale precum get,post,delete sau update . Modulul RouterModule este utilizat pentru a
permite rutarea aplicației, actualizând URL -ul în timp ce utiliza torul navigheaza prin
aplicației.

47
4.2. Arhitectura aplicației

Aplicația Ballroom Booker este compusă din partea ce conține serviciile și partea
responsabilă cu inte rfața către utilizator. Pentru generarea proiectului pe partea de client s -a
folosit Angular CLI ce oferă accesul rapid la o structură completă a unui proiect Angular și
care odată cu crearea acestuia impune anumite practici de urmat. Generatorul poate fi folosit
și pentru a genera diferite componente precum controllere, servicii, directive sau filtre.
Structura arborescenta a folderului app arată astfel:

Figura 4.1 . Folderul app

48
O component ă în Angular are structura prezentată în Figura 4.3.

Figura 4.2. Structura unui modul
Aplicația implementeaza modelul MVC în care se disting componentele de bază:
Model,View și Controller , comunicarea cu acestea realizându -se prin i ntermediul 2-Way-
Data-Binding . MVC este importat întrucât î ntr-o aplicație SPA, menținerea codului separat
este mai mult decât o tehnică bună, este esențial pentru a putea implementa cu succes o astfel
de aplicație.

Figura 4. 3. Modelul MVC in Angular.
(features -of-angularjs -that-make -it-the-best-for-web-development)

49

4.3. Structura bazei de date

Baza de date este formată din 7 tabele legate între ele după cum este prezentat în
Figura 4.4., datele primite de la utilizator fiind stocate folosind MySQL Server.

Figura 4.4 Schema bazei de date
Tabelul ballrooms poate fi considerat cel mai importat, acesta con ținând i nformațiile
de bază referitoare la un restaurant, denumirea respectivului restaurant și o desciere legată de
acesta și de serviciile oferite. Se pot observa de asemenea legăturile de tip one-to-many dintre
tabelul ballroom și tabelele contact, salons și menus , însemnând că un ballroom poate avea
mai multe saloane, poate pune la dispoziția utilizatorului mai multe meniuri și respectiv mai
multe persoane de contact . Privind legăturile din sens invers, mai multe saloane aparțin
aceluiași restaurant, pot fi p use la dispoziție mai multe meniuri în cadrul aceluiași ballroom,
pot exista mai multe persoane de contact pentru același restaurant .
Tabelul contacts conține informațiile legate de datele de contact, precum num ăr de
telefon, adresă, email sau site web ale persoanelor responsabile ce pot oferi mai multe detalii
sau pot ajuta în efectuarea unei rezervări ale unui anumit salon .

50
Tabelul salons cuprinde detalii ce constau în denumirea salonului , adresa la care se
găsește salonul respectiv, numărul maxim de persoane ce pot încăpea în acesta, suprafața și
dacă deține sau nu un ring de dans, o parcare privată sau o terasă .
Se pot observa alte doua legături de tip one-to-many dintre tabelul salons și tabelele
offersrequest și salonimages , însemnând ca un salon poate primi mai multe cereri de oferte
din partea utilizatorului și că va avea mai multe imagini cu acesta , menținute în tabelul
salonimages .
Tabelul offersrequest este cel care conține toate detaliile referitoare la tipul de
cerere de ofertă pe care un utiliza tor o efectuează asupra unui salon, precum : câteva date de
contact ale persoane care realizează cererea (nume, număr de telefon, email), tipul de
eveniment care va avea loc (petrecere aniversară, nuntă, banchet, evenimente corporate etc.),
numărul de invit ați, data la care va avea loc respectivul eveniment și un mesaj cu detalii
suplimentare.
Tabelul menus se referă la denumirea meniului, tipul acestuia, putând fi mic, mare sau
mediu, descierea detaliată a felurilor de mâncare și prețul fiecărui meniu.
Tabe lul admins cuprinde informațiile necesare logării în aplicație a unui utilizator,
username si parolă.
4.4. Cazuri de utilizare

În Figura 4.5 este prezentată diagrama Use Case a aplicației Ballroom Booker pentru
un utilizator obișnuit .

Figura 4.5 Diagrama Use Case pentru un user obișnuit

51
Un utilizator obișnuit va avea posibilitatea de a vizualiza totalitatea restaurantelor
existe nte, de a cauta restaurantul dorit după nume, de a filtra restaurantelor dupa anumite
criterii, și de a trimit e o cerere de închiriere a unui anumit restaurant.
În Figura 4.6 este prezentată diagrama Use Case a aplicației Ballroom Booker pentru
un admin unde se poate observa fluxul de evenimente pentru fiecare caz de utilizare .

Figura 4.6 Diagrama Use Case pen tru un admin

Utilizatorul de tip admin va putea realiza autentificarea în cadrul aplicației pe baza
unui nume de utilizator și a unei parole.
Acesta va avea astfel acces la modificarea tuturor detaliilor ce țin de restaurant,
saloane, meniuri și contacte, realizând astfel managementul acestora.
Adăugarea unui nou restaurant va implica, de asemenea, adăugarea unor contacte ale
acestuia, a unor meniuri puse la dispoziție pentru clienți, și a unor saloane unde pot avea loc
diferite petreceri.
Editarea uneia dintre aceste entități va consta în modificarea unuia sau mai multor
detalii legate de aceasta.
În ceea ce privește ștergerea unui restaurant, aceasta va duce la ștergerea în cascadă a
contactelor, meniurilor și saloanelor acelui restaurant, toate datele fiind eliminate din baza de
date.

52
4.5. Descriere aplicație – screenshoturi

Odată accesată aplicația Ballroom Booker , va fi afișată pagina de home, ce conține
prezentarea acesteia, după cum se poate observa și în imaginea din Figura 4. 7.

Figura 4.7. Pagina de home a aplicației

Prin navigarea utilizatorului către a doua pagină a meniului, numită Ballroo ms, acesta
este redirecționat către o pagină ce va conține totalitatea restaurantelor înscrise în cadrul
aplicației ce este prezentat ă în Figura 4.8 . Acestea sunt afișate în câte un element de tip mat-
card, împreună cu denumirea și două butoane, numite Details și Request Offer, ce permit
vizualizarea detaliilor despre restaurantul dorit și respectiv, cererea unei oferte de închiriere a
acestuia.
Utilizatorilor li se oferă posibilitatea de a căuta restaurantul dorit, în funcție de numele
acestuia, prin bara de căutare, poziționată deasupra tutoror cardurilor ce conțin restaurantele.
Introducerea în cadrul inputului a numelui restaurantului căutat va declanșa filtrarea tuturor
restaurantelor în funcție de valoarea introdusă, economisând astfel din timpul utili zatorului
interesat în găsirea unei anumite locații. Rezultatul unei astfel de cautări poate fi văzut în
Figura 4.9.

53

Figura 4.8. Pagina Ballrooms

Figura 4.9. Rezultat căutare restaurant

54

Căutarea restaurantelor este realizată prin implementarea unui Pipe denumit
LockFilter, aplicat ulterior, în fișierul HTML, asupra listei de restaurant parcurse cu *ngFor și
listatea în câte un element de tip mat-card.
Inputul de căutarea este plasat în interiorul unui element de tip mat-form-field.

<mat-form-field >
<input type="text" matInput placeholder ="Search" [(ngModel)]="query"
id="listSearch" >
</mat-form-field>

<mat-card class="card-picture" *ngFor=" let ballroom of allBallrooms |
LockFilter: query" >

Pipe-ul LockFilter are următorul cod:

import { Pipe, PipeTransform } from '@angular/core' ;

@Pipe({
name: 'LockFilter'
})

export class SearchPipe implements PipeTransform {
transform(value: any, args?: any): any {

if (!value) {
return null;
}
if (!args) {
return value;
}
args = args.toLowerCase();

return value.filter( function (item){
return JSON.stringify(item).toLowerCase().includes(args);
});
}
}

55
Prin apăsarea but onului Details , utilizatorul obișnuit va fi redirecționat către
componenta ce conține totalitatea detaliilor legate de restaurantul respectiv, acestea constând
în: totalitatea datelor de contact, la care pot fi cerute mai multe detalii decat cele prezentat e
deja pe site, o desciere a restaurantului, totalitatea meniurilor puse la dispoziție de către
restaurant, prețul acestora și descrierea lor, dar și prezentarea saloanelor ce intră în
componența restaurantului, către care poate fi trimisă o cerere de înch iriere.

Figura 4.10. Pagina de detalii a unui restaurant -contacte

Figura 4.11. Pagina de detalii a unui restaurant – saloane

56
Prin apăsarea butonului Request Offer , se va deschide un pop -up ce conțin e forma
prezentată în Figura 4.12 . Forma conține inputuri legate de tipul de eveniment ce se dorește a
fi organizat, numărul de invitați, data la care va avea loc evenimentul, numele, emailul și
numărul de telefon al persoanei care solicită oferta, și un mesaj cu detalii suplimentare.
Odată apăsat butonul Send, cererea de ofertă a utilizatorului va fi trimisă către
administratorul aplicației, care va contacta ulterior utilizatorul pentru a confirma cererea sau a
stabilii alte detalii legate de ofertă. Butonul Cancel , va anula cererea, acea sta nefiind trimisă
mai departe cătr e administrator.
Funcția sendRequest( offerRequest: OfferRequests) este cea care apelează funcția
din offerRequest.service.ts ce va trimite datele către server.
sendRequest(offerRequest: OfferRequests): void {
console.log( 'you submitted value: ' , offerRequest);
this.processValidation = true;
this.openSnackBar();
this.preProcessConfigurations();
if ( this.offer.id === null) {
this.offer.salonId = this.data.salonId;
this.offerRequestServi ce.sendOfferRequest(offerRequest)
.subscribe(successCode => {
this.statusCode = successCode;
this.dialogRef.close(offerRequest);

},
errorCode => this.statusCode = errorCode);
}
}
Funcția în Angular, care relizează trimiterea cererii, este următoarea:

// Send offer request
sendOfferRequest (offerRequest : OfferRequests ): Observable <number> {
// tslint:disable -next-line:prefer -const
let cpHeaders = new Headers({ 'Content -Type': 'application/json' });
// tslint:disable -next-line:prefer -const
let options = new RequestOptions ({ headers: cpHeaders });
return this.http.post(this.addOfferUrl , offerRequest , options)
.map(success => success.status)
.catch(this.handleError );
}
Aceasta utilizeaza modulul HttpModule , pentru a trimite o cerere de tip POST către
partea de server. Datele vor fi trimise sub forma unui obiect de tip JSON, vor fi preluate și
adăugate în baza de date a aplicației, mai exact în tabelul offersrequests .

57

Figura 4.12 . Cerere ofertă închiriere

În cazul în care vor fi lăsate câmpuri obligatorii necompletate, sau vor fi introduse date
greșite, vor apărea atențion ări sub fiecare input. Acestea vor conține mesaje precum “Trebuie
să introduceți un nume”, “Emailul nu este unul valid”, “Număr de telefon invalid. Vă rugăm
incercați din nou”. Validările inputurilor sunt realizate în funcțiile
getErrorMessage GuestNumber (),getErrorMessageName() ,getErrorMessagePhone() ,
getErrorMessageEmail().

getErrorMessage GuestNumber () {
return this.guestsNumber.hasError( 'required' ) ? 'You must enter a guests
number ' : '';
}
getErrorMessageName() {
return this.name.hasError( 'required' ) ? 'You must enter a name' :
this.name.hasError( 'minlength' ) ? 'Name must be at least 5 characters long.' :
this.name.hasError( 'maxlength' ) ? 'Name cannot be more than 30 characters
long.' : '' ;
}

58
getErrorMessagePhone() {
return this.phone.hasError( 'require d') ? 'You must enter a phone number' :
this.phone.hasError( 'pattern' ) ? 'Invalid phone number. Please try again.' :
'';
}
getErrorMessageEmail() {
return this.email.hasError( 'required' ) ? 'You must enter an email' :
this.email.hasError( 'email') ? 'Not a v alid email' :
'';
}

Figura 4.13. Mesaje de validare inputuri

Pentru ca un utilizator al Ballroom Booker să poată avea dreptul de a modifica în orice
fel datele existente în aplicație este necesa r ca acesta să fie un utilizator de tip admin.
Restricționarea se realizează prin asignarea adminului unui username și a unei parole pe baza
cărora se va putea autentifica, câștigând astfel dreptul de a face modificări ale datelor.
Prin apăsarea butonului Login din bara de meniu a aplicației va fi deschisă forma
pentru autentificare.

59

Figura 4 .14. Forma autentificare admin
Odată autentificat, adminul va fi redirecționat către pagina ce con ține totalitatea
restau rantelor înscrise în aplicație, împreună cu posibilitatea de filtrare a acestora după nume,
facilitând găsirea mai rapidă a restaurantului dorit.

Figura 4.1 5. Filtrarea restaurantelor după numele acestora

60

Figura 4.16 . Tabel ce con ține totalitatea restaurantelor

Acestuia i se ofera posibilitatea de a adăuga un nou restaurant, de a edita informațiile
despre unul deja existent, sau de șterge unul. Pentru a putea găsi cu ușurință restaurantul dorit,
utilizatorul de tip admin se poate folosii de secțiunea filter, ace asta permițându -i să realizeze
filtrarea restaura ntelor după numele acestora.
Dacă acesta va face click pe numele unuia dintre restaurante, va fi realizată navigarea
către pagina ce conține contactele, meniurile și saloanele restaurantului pe numele căruia s-a
făcut click. Pentru fiecare dintre acestea sunt afișate totalitatea contactelor puse la dispoziție
de restaurantul respectiv, totalitatea meniurilor, și respectiv, totalitatea saloanelor. De
asemenea pentru toate acestea se poate realiza adăugarea, mod ificarea sau ștergerea.

61

Figura 4.17. Tebelul ce conține totalitatea contactelor restaurantului numit Cosmopolitan

Forma pentru editarea unuia dintre contacte este afișată sub forma unui pop -up la
apăsarea butonului de editare, așa cum se prezintă în figura Figura 4.18.
Funcția updateContact() ce se găsește în fișierul contact.service.ts este cea care
realizează editarea contactului. Aceasta folosește modulul oferi t de către Angular, HttpModule
pentru a realiza o cerere de tip PUT ce va fi trimisă către server.

// Update contact
updateContact (contact: Contact): Observable <number> {
// tslint:disable -next-line:prefer -const
let cpHeaders = new Headers({ 'Content -Type': 'application/json' });
// tslint:disable -next-line:prefer -const
let options = new RequestOptions ({ headers: cpHeaders });
return this.http.put(this.updateContactUrl , contact, options)
.map(success => success.status)
.catch(this.handleError );
}

62

Figura 4.18. Editarea unui contact

Adăgarea unui nou salon în cadrul unui restaurant se realizează prin intermediul
funcției createSalon() din fișierul salon.service.ts , aceasta trimițând o cerere de tip POST
către server. Forma de adăugare a unui sal on poate fi văzută în Figura 4.19 .
// Create salon
createSalon (salon: Salon): Observable <number> {
// tslint:disable -next-line:prefer -const
let cpHeaders = new Headers({ 'Content -Type': 'application/json' });
// tslint:disable -next-line:prefer -const
let options = new RequestOptions ({ headers: cpHeaders });
return this.http.post(this.addSalonUrl , salon, options)
.map(success => success.status)
.catch(this.handleError );
}

63

Figura 4.19. Adăgarea unui salon
Dacă administratorul omite completarea câmpurilor obligatorii, sau sunt efectuate
anumite greșeli la completare, mesaje de atenționare vor fi afișate pentru acesta.

Figura 4.20. Mesaje de atenționare

64
Dacă se dorește eliminarea unui meniu, spre exemplu, odată apăsat butonul de ștergere
pentru un anumit meniu, va apărea un pop -up de confirmare. Același lucru se va întâmpla și la
ștergerea unui restaurant, contact sau salon.

Figura 4.21. Ștergerea unui meniu
Funcția deleteMeniu ById() ce realizează ștergerea se află în fișierul menu.service.ts
și trimite o cerere Http de tip DELETE către server.
// Delete menu
deleteMenuById (id: string): Observable <number> {
// tslint:disable -next-line:prefer -const
let cpHeaders = new Headers;
cpHeaders .append('Content -Type', 'application/json' );
cpHeaders .append('Access-Control-Allow-Origin' , '*');
cpHeaders .append('Access-Control-Allow-Methods' , '*');

// tslint:disable -next-line:prefer -const
let cpParams = new URLSearchParams ();
cpParams .set('id', id );
// tslint:disable -next-line:prefer -const
let options = new RequestOptions ({ params: cpParams });
return this.http.delete(this.deleteMenuUrl , options)
.map(success => success.status)
.catch(this.handleError );
}

65

CONCLUZII

În concluzie, a rhitectura SPA constituie una dintre cele mai recente evoluții în designul
aplicațiilor web, iar prin intermediul a diverse biblioteci JavaScript și tool -uri cum ar fi
Angular, permite dezvoltatorilor să creeze aplicații web care foarte rar apelează serverul
pentru a încărca o pagină HTML nouă. O aplicație SPA funcționează în interiorul unui
browser și nu necesită reîncărcarea paginii în timpul utilizării, menținând utilizatorul într -un
spațiu web confortabil, în care conținutul este prezentat într -un mod simplu, ușor și
funcțional.
Angular este o platformă și un framework pentru crearea de aplicații SPA client în
HTML și TypeScript care face aplicațiile web mai ușor de construit, A ngularul însuși fiind
scris in limbajul TypeScript .
Angular are mai multe tipuri de entități de nivel superior cu roluri specifice și
capabilități folosite în diverse combinații pentru a crea aplicația dorită :
 Module – Obiecte care ajută la organizarea dependențelor în unități discrete
 Componente – Noi elemente care vor compune majoritatea structurii și logicii aplicației
 Directive – Obiecte care modifică elementele pentru a le oferi noi capacități sau pentru a
le schimba comportamentele
 Pipe – Funcții care formatează date înainte ca acestea să fie redate
 Servicii – obiecte reutilizabile care completează roluri de nișă, cum ar fi accesul la date
sau utilitarele auxiliare
În primul capitol al lucrării au fost prezentate conceptele de bază ale unei arhitecturi
SPA(Single Page Application), prin comparația acesteia cu arhitectura tradițională. De
asemenea au fost prezentate modelele MV*, unele dintre cele mai notabile fiind M odel-View –
Controller (MVC), Model -View -Presenter (MVP) și Model -View -ViewModel (MVVM),
împreuna cu moaditățile de navigare și comunicare cu serverul în SPA.
Capitolul doi prezintă limbajul TypeScript fiind menționate tipurile de date din
TypeScript, funcți ile și tipurile de fu ncții, intefețele , decoratorii, totodată fiind descrisă
compoziția componentelor și client -side routingul.
În al treilea capitol este realizată descrierea conceptelor de bază ale frameworkului
Angular, prin prezentarea arhitecturii un ei aplicații Angular, a modulelor, componentelor,

66
comunicarea dintre componenete împreună cu ciclul de viață al acestora, router în Angular,
directivele, piepe -urile, observables și tipurile de forme cele mai utilizate, template -driven
forms și reactive fo rms.
Ultimul capitol conține doar informații referitoare la aplicația dezvoltată , numită
Ballroom Booker Management Syste m, ce realizează managementul restaurantelor unde pot fi
realizate o serie de evenimente, și oferă o selecție a locațiilor, ajutând ast fel la economisirea
timpului utilizatorilor prin restrângerea căutărilor. Este prezentată arhitectura aplicației,
structura bazei de date, cazurile de utilizare pentru un user normal si un admin, și descrierea
aplicației prin screen -schouturi.

67

BIBLIOGRAFIE

Web -grafie
https://angular.io/
https://www.quora.com/What -is-SPA-single -page -application
https://medium.com/mvc -mvp-and-mvvm -design -pattern
https://dzone.com/articles/communication -betwe en-components -using -input -in-an
https://angular.io/guide/http
https://www.todaysoftmag.ro/article/2117/typescript -react -si-redux -sa-alegem -cele-
mai-bune -tooluri -pentru -aplicatiile -web
https://www.mat ridtech.net/blog/5 -key-features -of-angularjs -that-make -it-the-best-for-
web-development/

Similar Posts