U ovom ću blog postu napraviti jednostavnu Angular CRUD (create, read, update, delete) aplikaciju koja će se sastojati od forme za pregled podataka uz mogućnost dodavanja, uređivanja i brisanja podataka.
CRUD operacije nešto su s čime se svaki web developer najčešće susreće i zato bi ovaj primjer posebno mogao biti koristan novim developerima ili onima koji će to tek postati.
Uvod
Cilj ovog blog posta je pokazati:
– kako kreirati Angular projekt koristeći Angular CLI
– kako kreirati i koristiti servis pomoću kojega ću pozivati JSON API
– kako dodati Bootstrap za brže kreiranje forme za unos, pregled, uređivanje i brisanje sadržaja
Kreiranje Angular projekta
Pomoću Angular CLI-a kreirat ću novi projekt.
|
1 2 |
$ ng new AngularCRUD $ ng serve |
Ako projekt sada otvorim u web pregledniku na adresi http://localhost:4200/ dobit ću sljedeće
S obzirom da umjesto toga želim imati formu za unos, pregled, uređivanje i brisanje sadržaja prvo ću dodati podršku za Bootstrap na način da u index.html dodam
|
1 |
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> |
. I sada mogu koristiti Bootstrap komponente.
Kasnije ću se vratiti na izgled forme, a sada idem postaviti glavni dio funkcionalnosti koji se tiče kreiranja servisa i pozivanja API-ja.
Kreiranje servisa za API
Servis pomoću kojega ću vršiti sve upite na API kreiram naredbom
|
1 |
$ ng generate service KorisniciAPI |
Nakon čega dobijem korisnici-api.service.ts
|
1 2 3 4 5 6 7 8 |
import { Injectable } from '@angular/core'; @Injectable() export class KorisniciApiService { constructor() { } } |
Servis se može koristiti za različite svrhe, ali kako ću meni ovdje glavna svrha biti slanje upita na API znači da obavezno moram koristiti Http servis.
Konačan izgled servisa može se vidjeti u nastavku, a njime je pokriveno sve – od pregleda svih korisnika, dodavanja novih, uređivanja i brisanja postojećih.
|
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 |
import { Injectable } from '@angular/core'; import { Http } from '@angular/http'; import 'rxjs/add/operator/map'; @Injectable() export class KorisniciApiService { constructor(private _http: Http) {} // Pregled svih korisnika u imeniku svi(){ return this._http.get('http://localhost:3000/Imenik') .map(res => res.json()); } // Dodavanje korisnika u imenik dodaj(a:any){ return this._http.post('http://localhost:3000/Imenik', a) .map(res => res.json()); } // Uređivanje korisnika u imeniku uredi(a:any){ return this._http.put('http://localhost:3000/Imenik/' + a.id, a) .map(res => res.json()); } // Brisanje korisnika iz imenika obrisi(a:any){ return this._http.delete('http://localhost:3000/Imenik/' + a) .map(res => res.json()); } } |
Izgled forme (app.component.html)
Za izgled forme iskoristit ću Bootstrap komponente. Struktura forme nalazi se unutar app.component.html, a izgleda ovako:
|
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 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
<div class="container-fluid"> <div class="row"> <div class="col-lg-8"> <div class="panel panel-default"> <div class="panel-heading">Dodaj/Uredi korisnika:</div> <div class="panel-body"> <form name="ImenikForma" novalidate> <div class="form-group"> <div class="row"> <div class="col col-lg-5 col-md-5" ng-class="{ 'has-error' : ImenikForma.ime.$invalid && !ImenikForma.ime.$pristine }"> <div id="input_container"> <input type="text" class="form-control" id="ime" required maxlength="30" placeholder="Ime i prezime" [(ngModel)]="korisnik.ime" [ngModelOptions]="{standalone: true}" #ime="ngModel"> </div> </div> <div class="col col-lg-5 col-md-5" ng-class="{ 'has-error' : ImenikForma.telefon.$invalid && !ImenikForma.telefon.$pristine }"> <div id="input_container"> <input type="tel" class="form-control" id="telefon" required placeholder="Telefon" [(ngModel)]="korisnik.telefon" [ngModelOptions]="{standalone: true}" #telefon="ngModel"> </div> </div> <div class="col col-lg-2 col-md-2"> <div id="input_container"> <div *ngIf="spremi" class="text-center"><button type="button" class="btn btn-success btn-md" (click)="dodajKorisnika(korisnik)" [disabled]="!ime.valid || !telefon.valid"> Spremi </button></div> <div *ngIf="!spremi" class="text-center"><button type="button" class="btn btn-success btn-md" (click)="urediKorisnika2(korisnik)" [disabled]="!ime.valid || !telefon.valid"> Uredi </button></div> </div> </div> </div> </div> </form> </div> </div> </div> </div> <div class="row"> <div class="col-lg-8"> <div class="panel panel-default"> <div class="panel-heading">Ukupno korisnika: {{ukupanbrojkorisnika}}</div> <div class="panel-body"> <form novalidate> <div > <span *ngIf="ukupanbrojkorisnika < 1">Nema podataka</span> <table *ngIf="ukupanbrojkorisnika > 0" class="table table-striped table-hover table-responsive" ng-switch-default> <thead> <tr> <th class="tablica text-center">Rb.</th> <th class="tablica text-center">Ime</th> <th class="tablica text-center">Telefon</th> <th class="tablica text-center">Uredi | Obriši</th> </tr> </thead> <tbody> <tr *ngFor="let kor of svikorisnici; let i = index"> <td class="tablica text-center">{{i+1}}.</td> <td class="tablica text-center">{{kor.ime}}</td> <td class="tablica text-center">{{kor.telefon}}</td> <td class="tablica text-center"> <button class="btn btn-info btn-sm" (click)="urediKorisnika(kor)"><i class="glyphicon glyphicon-edit"></i></button> <button class="btn btn-danger btn-sm" (click)="obrisiKorisnika(kor)"><i class="glyphicon glyphicon-trash"></i></button> </td> </tr> </tbody> </table> </div> </form> </div> </div> </div> </div> </div> |
Forma na početku i bez podataka izgleda ovako:
Sada kada imam definiran izgled forme mogu kreirati opcije koje će joj dati funkcionalnost.
Dodavanje (POST)
Što se dodavanja sadržaja tiče nije ga moguće dodati dok sva obavezna polja nisu unesena. U ovom slučaju postoje dva polja, ime i prezime te broj telefona, i oba su obavezna. S obzirom da u formi za sada nema niti jednog korisnika *ngIf="ukupanbrojkorisnika < 1" prikezuje se poruka “Nema podataka”.
|
1 2 3 4 5 6 7 8 9 |
dodajKorisnika(korisnik){ this._korisniciService.dodaj(korisnik).subscribe( res => { console.log(res); this.dohvatiSveKorisnike(); this.korisnik.ime = ' '; this.korisnik.telefon = ' '; }); } |
Nakon dodavanja korisnika popis se automatski osvježava i prikazuje sve dodane korisnike.
Pregled (GET)
Kada se Angular web aplikacija pokrene automatski se dohvaća popis svih do tada unesenih korisnika. Za tu svrhu koristim ngOnInit() što je dio Angular Lifecycle Hook.
|
1 2 3 4 5 6 7 8 9 10 11 |
ngOnInit() { this.dohvatiSveKorisnike(); } dohvatiSveKorisnike(){ this._korisniciService.svi().subscribe(res => { console.log(res); this.svikorisnici = res; this.ukupanbrojkorisnika = res.length; }); } |
Također, odmah dohvaćam i dužinu niza this.ukupanbrojkorisnika = res.length; kako bi mogao prikazati ukupan broj korisnika.
Uređivanje (PUT)
Kod uređivanja korisnika imam dvije funkcije. Prva urediKorisnika(); dohvaća podatke odabranog korisnika i prikazuje ih u gornjoj formi za unos/uređivanje, a druga urediKorisnika2(); obavlja proces uređivanja odabranog korisnika tj. šalje nove podatke na API.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
urediKorisnika(kor){ console.log(kor); this.spremi = false; this.korisnik.id = kor.id; this.korisnik.ime = kor.ime; this.korisnik.telefon = kor.telefon; } urediKorisnika2(korisnik){ console.log(korisnik); this._korisniciService.uredi(korisnik).subscribe( res => { console.log(res); this.dohvatiSveKorisnike(); this.korisnik.ime = ' '; this.korisnik.telefon = ' '; this.spremi = true; }); } |
Nakon što su novi podaci poslani popis korisnika se automatski osvježava, a gumb ‘Uredi’ ponovno postaje ‘Spremi’.
Brisanje (DELETE)
Brisanje korisnika zadnji je korak izrade ovog CRUD primjera. Nakon što je odabrani korisnik obrisan popis se automatski osvježava.
|
1 2 3 4 5 6 7 8 9 10 |
obrisiKorisnika(kor){ let id = kor.id; if(window.confirm('Jeste li sigurni da želite obrisati korisnika?')){ this._korisniciService.obrisi(id).subscribe( res => { console.log(res); this.dohvatiSveKorisnike(); }); } } |
Zaključak
Ovo je bio jednostavan primjer Angular CRUD forme. Mogao sam ovdje dodatno uljepšati izgled forme ili na drugačiji način slati upite na API, ali mislim da je ovo sasvim dovoljno za početak jer kako god bilo korištenjem ovog primjera može se napraviti funkcionalna forma za unos, pregled, uređivanje i brisanje sadržaja.
I za kraj, NPM paketi korišteni u ovom primjeru:
|
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 49 |
{ "name": "angular-crud", "version": "0.0.0", "license": "MIT", "scripts": { "ng": "ng", "start": "ng serve", "build": "ng build", "test": "ng test", "lint": "ng lint", "e2e": "ng e2e" }, "private": true, "dependencies": { "@angular/animations": "^4.2.4", "@angular/common": "^4.2.4", "@angular/compiler": "^4.2.4", "@angular/core": "^4.2.4", "@angular/forms": "^4.2.4", "@angular/http": "^4.2.4", "@angular/platform-browser": "^4.2.4", "@angular/platform-browser-dynamic": "^4.2.4", "@angular/router": "^4.2.4", "core-js": "^2.4.1", "rxjs": "^5.4.2", "zone.js": "^0.8.14" }, "devDependencies": { "@angular/cli": "1.4.7", "@angular/compiler-cli": "^4.2.4", "@angular/language-service": "^4.2.4", "@types/jasmine": "~2.5.53", "@types/jasminewd2": "~2.0.2", "@types/node": "~6.0.60", "codelyzer": "~3.2.0", "jasmine-core": "~2.6.2", "jasmine-spec-reporter": "~4.1.0", "karma": "~1.7.0", "karma-chrome-launcher": "~2.1.1", "karma-cli": "~1.0.1", "karma-coverage-istanbul-reporter": "^1.2.1", "karma-jasmine": "~1.1.0", "karma-jasmine-html-reporter": "^0.2.2", "protractor": "~5.1.2", "ts-node": "~3.2.0", "tslint": "~5.7.0", "typescript": "~2.3.3" } } |













