Cilj blog posta “*ngFor u Angularu za početnike” je napraviti uvod u ngFor Angular direktivu jer ona je osnova koju svaki, Angular, developer treba i mora znati.
*ngFor direktiva se primarno koristi za prikaz niza podataka (array) i početnicima može predstavljati poseban izazov. Također, može se koristiti i za prikaz objekata uz pomoć KeyValuePipe.
Prije nego krenem s izradom primjera trebam kreirati Angular projekt, a to činim naredbom:
1 2 3 |
$ ng new AngularNgFor $ cd AngularNgFor $ ng serve |
Projekt je vidljiv na adresi http://localhost:4200/
Uvod
*ngFor direktiva u Angularu, osim što služi za prikaz niza podataka, je optimizirana da minimalno utječe na DOM (Document Object Model).
To će se najbolje vidjeti u nastavku kada budem koristio let i = index pri čemu ću uklanjati elemente niza bez da ga cijelog ponovno osvježavam.
Angular će se pobrinuti za to da samo taj jedan element izbaci dok sve drugo ostaje isto. Isti slučaj bi bio i kada bi htio dodati novi element u niz.
U slučaju kada podatke dohvaćamo putem nekog API-ja dogodit će se, u slučaju kada se neki podataka obriše ili doda, da Angular više neće znati što treba biti na kojoj poziciji. U tom slučaju koristim trackBy putem čega Angularu mogu reći koji parametar da koristi kako bi identificirao elemente.
*ngFor – prikaz niza podataka
Ako npr. imam sljedeći niz podatka za pretpostaviti je da ih želim na ekranu prikazati kao popis. U ovom će slučaju to biti jednostavan popis osoba. Podaci su fiksno određeni unutar niza, ali logika je ista čak i da stižu putem nekog API-ja.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
simpleArray = [ { id: 4, name: 'Tomislav', country: 'Croatia' }, { id: 5, name: 'Jomislav', country: 'Croatia' }, { id: 6, name: 'Valsimot', country: 'Croatia' }, ] |
Gore navedeni popis podataka želim prikazati na sljedeći način:
1 2 3 4 5 |
<ul> <li>Tomislav, Croatia</li> <li>Jomislav, Croatia</li> <li>Valsimot, Croatia</li> </ul> |
To znači da nekako moram postići da se za svaki objekt unutar niza kreira novi <li></li> element.
Upravo tu uskače *ngFor sa vrlo jednostavnom sintaksom *ngFor="let <value> of <collection>" pri čemu <value> označava naziv varijable koji proizvoljno određujem, dok <collection> označava izvor podataka što je u ovom slučaju niz simpleArray.
1 2 3 |
<ul> <li *ngFor="let data of simpleArray">{{data.name}}, {{data.country}}</li> </ul> |
Konačni rezultat je sljedeći:
Ako želim imati redne brojeve mogu koristiti ol tag. Ovo spominjem samo iz razloga što ću u nastavku pokazati kako je redne brojeve moguće dobiti i pomoću indexa elementa.
*ngFor + element index
index se definira kao varijabla let i = index i uvijek počinje od 0. Mogu ga koristiti kako bi prikazao redne brojeve elemenata.
1 2 3 |
<ul> <li *ngFor="let data of simpleArray; let i = index">{{i+1}} - {{data.name}}, {{data.country}}</li> </ul> |
Na ekranu to izgleda ovako:
index mogu, ali i ne moram prikazati na ekranu. U oba ga slučaja mogu koristiti kako bi pristupio pojednom elementu niza.
U sljedećem ću primjeru pomoću funkcije removeByIndex(i) ukloniti neke elemente iz niza.
1 2 3 4 5 |
removeByIndex(i){ console.log(i); this.simpleArray.splice(i,1); console.log(this.simpleArray); } |
Funkciju pozivam klikom na pojedini element.
1 2 3 |
<ul> <li *ngFor="let data of simpleArray; let i = index" (click)="removeByIndex(i)">{{i}} - {{data.name}}, {{data.country}}</li> </ul> |
U praksi to izgleda ovako:
*ngFor + trackBy
trackBy se definira kao ; trackBy: id.
1 2 3 |
<ul> <li *ngFor="let data of simpleArray; let i = index; trackBy: id" (click)="trackElement(i,data.id)">{{data.name}}, {{data.country}}</li> </ul> |
Pomoću funkcije trackElement(i,data.id) dohvaćam unikatni ID svakog elementa niza.
1 2 3 |
trackElement(i: number, element: any) { console.log("index:" + " " + i + ", " + "trackBy ID:" + " " + element); } |
U praksi to izgleda ovako:
*ngFor – prvi i zadnji element niza
*ngFor direktiva u Angularu nudi još jednu zanimljivu mogućnost, a to je dohvaćanje prvog i zadnjeg elementa niza pomoću ; let first = first; let last = last.
1 2 3 |
<ul> <li *ngFor="let data of simpleArray; let first = first; let last = last" [ngClass]="{ firstClass: first, lastClass: last }">{{data.name}}, {{data.country}}</li> </ul> |
Na taj se način prvi i zadnji element mogu npr. urediti CSS-om.
1 2 3 4 5 6 |
.firstClass { color: red; } .lastClass { color: blue; } |
U praksi to izgleda ovako:
Iako ovo još nisam koristio u nekoj produkcijskoj aplikaciji izgleda vrlo zanimljivo.
*ngFor – parni i neparni elementi niza
Kada već spominjem uređivanje elementata CSS-om, postoji još jedna zanimljiva funkcionalnost korištenjem ; let even = even; let odd = odd.
1 2 3 |
<ul> <li *ngFor="let data of simpleArray; let even = even; let odd = odd" [ngClass]="{ evenClass: even, oddClass: odd }">{{data.name}}, {{data.country}}</li> </ul> |
Na taj se način parni i neparni elementi mogu npr. urediti CSS-om.
1 2 3 4 5 6 |
.evenClass { color: red; } .oddClass { color: blue; } |
U praksi to izgleda ovako:
*ngFor – niz unutar niza
Osim prikaza osnovnog niza mogu prikazati i napredni niz tj. countryList niz unutar nestedArray niza.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
nestedArray: any[] = [ { id: 4, name: 'Tomislav', countryList: [ { shortCode: 'HR', fullName: 'Croatia' }, { shortCode: 'UK', fullName: 'United Kingdom' } ] }, { id: 5, name: 'Jomislav', countryList: [ { shortCode: 'HR', fullName: 'Croatia' }, { shortCode: 'UK', fullName: 'United Kingdom' } ] }, { id: 6, name: 'Valsimot', countryList: [ { shortCode: 'HR', fullName: 'Croatia' }, { shortCode: 'UK', fullName: 'United Kingdom' } ] }, ] |
U ovom slučaju *ngFor ide unutar <ul>.
1 2 3 4 5 6 7 8 |
<ul *ngFor="let data of nestedArray"> <li>{{data.name}}</li> <ul> <li *ngFor="let country of data.countryList"> {{country.fullName}} </li> </ul> </ul> |
U praksi to izgleda ovako:
Zaključak
U ovom blog postu, pod nazivom “*ngFor u Angularu za početnike“, naveo sam osnovne funkcionalnosti *ngFor direktive s kojom svaki developer može napraviti funkcionalno rješenje. Sve dalje ovisi o specifičnim potrebama projekta.
P.S. Struktura projekta prema package.json:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
{ "name": "angular-ng-for", "version": "0.0.0", "scripts": { "ng": "ng", "start": "ng serve", "build": "ng build", "test": "ng test", "lint": "ng lint", "e2e": "ng e2e" }, "private": true, "dependencies": { "@angular/animations": "~7.2.0", "@angular/common": "~7.2.0", "@angular/compiler": "~7.2.0", "@angular/core": "~7.2.0", "@angular/forms": "~7.2.0", "@angular/platform-browser": "~7.2.0", "@angular/platform-browser-dynamic": "~7.2.0", "@angular/router": "~7.2.0", "core-js": "^2.5.4", "rxjs": "~6.3.3", "tslib": "^1.9.0", "zone.js": "~0.8.26" }, "devDependencies": { "@angular-devkit/build-angular": "~0.13.0", "@angular/cli": "~7.3.9", "@angular/compiler-cli": "~7.2.0", "@angular/language-service": "~7.2.0", "@types/node": "~8.9.4", "@types/jasmine": "~2.8.8", "@types/jasminewd2": "~2.0.3", "codelyzer": "~4.5.0", "jasmine-core": "~2.99.1", "jasmine-spec-reporter": "~4.2.1", "karma": "~4.0.0", "karma-chrome-launcher": "~2.2.0", "karma-coverage-istanbul-reporter": "~2.0.1", "karma-jasmine": "~1.1.2", "karma-jasmine-html-reporter": "^0.2.2", "protractor": "~5.4.0", "ts-node": "~7.0.0", "tslint": "~5.11.0", "typescript": "~3.2.2" } } |