Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
In questo articolo, descrivo alcune delle funzionalità principali incluse nella release 5 di Angular
(UPDATE: l’articolo è stato aggiornato alla versione 6), uno dei framework più utilizzati nella
creazione di Single-Page Applications (SPA).
Il risultato finale dell’applicazione sarà un elenco di smartphone con un form per la gestione di
tutte le operazioni CRUD:
lettura (GET), inserimento (POST), cancellazione (DELETE) e modifica degli elementi
(PUT/PATCH).
Revoca cookie
NodeJS e NPM
Per installare gli strumenti necessari a svolgere questo tutorial è indispensabile e ettuare il
download di NodeJS, installarlo e verificare la possibilità di utilizzare il comando npm (Node
Package Manager) da terminale, che è incluso nell’installer di Node.
Dopo aver atteso qualche secondo / minuto sarà quindi possibile generare un progetto Angular
utilizzando semplicemente il modulo ng, disponibile dopo l’installazione della CLI (Command
Line Interface).
1. ng new my-project
Il risultato sarà la creazione di una struttura simile alla seguente (potrebbe variare leggermente
in base alla versione di angular-cli che state utilizzando):
Revoca cookie
Una volta terminato il processo, il progetto potrà essere avviato utilizzando il comando npm
start
1. cd my-project
L’opzione --save non è più necessaria dalla versione 5 di npm perché abilitata di
default
O la più concisa:
1 "styles": [
2 "../node_modules/bootstrap/dist/css/bootstrap.min.css",
3 "../node_modules/font-awesome/css/font-awesome.min.css",
Revoca cookie
4 "styles.css"
5 ],
Per far in modo che la modifica abbia e etto è necessario “killare” il processo npm start
avviato in precedenza (utilizzando ad esempio CTRL + C o CMD + C) e riavviarlo con npm start.
TIP: Angular-cli utilizza WebPack dietro le quinte, un mix tra un automation tool e
un module bundler, allo scopo di compilare il progetto, generare le build, gestire
CSS/SASS e molto altro. Il file angular-cli.json permette di configurare alcune
funzionalità di WebPack senza tuttavia dover necessariamente conoscere lo
strumento. Maggiori informazioni sul repository GitHub di angular-cli
Esistono diversi strumenti in grado di creare un set di servizi (mock) REST in pochi minuti ma uno
dei più apprezzati è senza dubbio json-server.
Il funzionamento è molto semplice. Si crea un file .json, si avvia json-server da riga di comando e
in pochi secondi saranno disponibili delle API REST per la manipolazione del JSON:
Dopo aver installato il pacchetto sarà su iciente creare un file, ad esempio db.json, e inserire
all’interno di questo file una struttura JSON. Per il nostro esempio creeremo una lista di devices:
1 {
2 "devices": [
3 {
4 "label": "One Plus 8",
5 "os": "android",
6 "price": 750,
7 "rate": 3,
8 "memory": 7400,
9 "desc": "One Plus 5 is a flagship phone...",
10 "id": 2
11 },
12 {
13 "label": "IPhone 7 +",
14 "os": "ios",
15 "price": 700,
16 "rate": 3,
17 "memory": 3000,
18 "desc": "",
19 "id": 24
20 }
21 ],
22 "login": {
23 "token": "efoiwejo32r32-fake-token"
24 }
25 }
Per avviare il server sarà quindi su iciente posizionarsi da terminale nella cartella in cui si è
creato il file db.json e avviare digitare la seguente istruzione:
Revoca cookie
Ora avremo a disposizione un set di API per manipolare la nostra collezione di devices.
Sarà infatti possibile e ettuare operazioni in POST, GET, PUT, PATCH e DELETE semplicemente
invocando l’endpoint generato dal server, in questo caso:
1. http://localhost:3000/devices
2. http://localhost:3000/login
Carichiamo ora una collezione dati dal server mock creato con json-server.
1 // app.component.ts
2 import { Component } from '@angular/core';
3 import { HttpClient } from '@angular/common/http';
4
5 @Component({
6 selector: 'app-root',
7 templateUrl: './app.component.html',
8 styleUrls: ['./app.component.css']
9 })
10 export class AppComponent {
11
12 constructor(private http: HttpClient) {
13 this.getAll();
14 }
15
Revoca cookie
16 getAll() {
17 this.http.get('http://localhost:3000/devices')
18 .subscribe(result => console.log(result));
19 }
20 }
1) Se non avete avviate il server JSON, come descritto in precedenza, non avrete a disposizione
l’end-point dal quale recuperare la collezione dati.
Il mio consiglio è quello di creare una cartella server nella root del progetto (quindi fuori dalla
cartella /src) e di avviare il comando da terminale : json-server --watch
server/db.json.
1 // app.module.ts
2 import { BrowserModule } from '@angular/platform-browser';
3 import { NgModule } from '@angular/core';
4
5 import { AppComponent } from './app.component';
6 import { HttpClientModule } from '@angular/common/http';
7 import { FormsModule } from '@angular/forms';
8 Revoca cookie
9 @NgModule({
10 declarations: [
11 AppComponent
12 ],
13 imports: [
14 BrowserModule, HttpClientModule, FormsModule
15 ],
16 providers: [],
17 bootstrap: [AppComponent]
18 })
19 export class AppModule { }
Salviamo tutti i files, avviate il browser e navigate all’indirizzo http://localhost:4200. Aprite i Dev
Tools (se usate Chrome: F12 su windows oppure CMD + OPTIONS + i su Mac) e dovreste vedere il
risultato nella console dei dev tools:
Model e tipizzazione
Per sfruttare le potenzialità del linguaggio Typescript, alla base del framework Angular, possiamo
creare un custom type che rappresenti i nostri device.
Sarà utile per tutta una serie di motivi: abilitare intellisense e autocompletamento negli
editor/IDE, ricevere errori dal compilatore qualora utilizzassimo delle proprietà errate,
documentare il codice, solo per citarne alcuni.
1 // src/model/device.ts
2 export interface Device {
3 id?: number;
4 label?: string;
5 os?: string;
6 price?: number;
7 memory?: number;
8 rate?: number;
9 desc?: string;
10 }
Revoca cookie
TIP: il punto di domanda (?) indica che la proprietà sarà facoltativa. Sarebbe
preferibile evitarlo in un contesto reale ma, ai fini didattici, se ipotizziamo di non
gestire tutte le proprietà di un device, come in questo scenario, è preferibile
utilizzare questo approccio per evitare errori del compiler.
1 // src/app.component.ts
2 import { Component } from '@angular/core';
3 import { HttpClient } from '@angular/common/http';
4 import { Device } from './model/device';
5
6 @Component({
7 selector: 'app-root',
8 templateUrl: './app.component.html',
9 styleUrls: ['./app.component.css']
10 })
11 export class AppComponent {
12 devices: Device[];
13
14 constructor(private http: HttpClient) {
15 this.getAll();
16 }
17
18 getAll() {
19 this.http.get<Device[]>('http://localhost:3000/devices')
20 .subscribe(result => this.devices = result);
21 }
22 }
TIP: le direttive sono dei “componenti speciali” che possono essere applicati al
DOM o ad altri componenti. Angular include un set di direttive molto utili per
manipolare il dom (ngIf, ngClass, ecc.) ma potete chiaramente creare direttive
personalizzate
Possiamo ora completare il template visualizzando altre proprietà del device e utilizzando
alcune delle classi CSS messe a disposizione da Bootstrap e FontAwesome.
Revoca cookie
Cancellazione e selezione di un elemento
1 // src/app.component.ts
2 import { Component } from '@angular/core';
3 import { HttpClient } from '@angular/common/http';
4 import { Device } from './model/device';
5
6 @Component({
7 selector: 'app-root',
8 templateUrl: './app.component.html',
9 styleUrls: ['./app.component.css']
10 })
11 export class AppComponent {
12 devices: Device[];
13 active: Device = {};
14
15 constructor(private http: HttpClient) {
16 // console.log ('environment:', env);
17 this.getAll();
18 }
19
20 getAll() {
21 this.http.get<Device[]>('http://localhost:3000/devices')
22 .subscribe(result => this.devices = result);
23 }
24
25 setActive(device: Device) {
26 this.active = device;
27 }
28
29
30 delete(event: MouseEvent, device: Device) {
31 event.stopPropagation()
32 this.http.delete<any>(`http://localhost:3000/devices/${device.i
33 .subscribe(
34 () => {
35 const index = this.devices.indexOf(device)
36 this.devices.splice(index, 1);
37 }
38 );
39 }
40
41 }
Revoca cookie
Il metodo setActive salva una reference dell’elemento in una proprietà active
che sarà successivamente utilizzata per popolare il form ed e ettuare la modifica
delle proprietà del device selezionato
Modifichiamo quindi il template per invocare i due metodi appena creati e per visualizzare
l’elemento selezionato proprio sopra la lista (in cui successivamente posizioneremo il form).
Utilizziamo inoltre la direttiva ngClass per evidenziare l’elemento selezionato.
1 <pre>{{active | json}}</pre>
2
3 <div class="card bg-dark text-white mb-3">
4
5 <!--Devices List -->
6 <div *ngFor="let device of devices"
7 class="list-group-item list-group-item-action"
8 [ngClass]="{'bg-warning text-dark': device.id === active?.id
9 (click)="setActive(device)">
10
11 <!--os icon-->
12 <i class="fa"
13 [ngClass]="{
14 'fa-android': device.os === 'android',
15 'fa-apple' : device.os === 'ios',
16 'fa-tablet' : device.os === 'others'
17 }"
18 ></i>
19
20
21 <!--label-->
22 <i class="fa fa-in"></i>
23 <span>{{device?.label}}</span>
24
25 <!--display rate-->
26 <!--...missing...-->
27
28 <div class="pull-right">
29 <!--price -->
30 <strong *ngIf="device.price"
31 [style.color]="device.price > 500 ? 'red' : null">
32 € {{device.price | number: '1.2-2'}}
33 </strong>
34
35 <!--trash icon-->
36 <i class="fa fa-trash icon"
37 (click)="delete($event, device)"></i>
38 </div> Revoca cookie
39 </div>
40 </div>
Come potete notare notato che al metodo delete passo la proprietà $event,
ovvero l’evento del mouse generato dal click dell’utente. In questo modo è
possibile invocare l’istruzione event.stopPropagation() per evitare che anche
il metodo setActive sia invocato al click sull’icona “trash”. Maggiori info sulla
documentazione MDN
Revoca cookie
Angular Form
Una delle funzionalità più amate di Angular è la gestione dei form, superiore per quantità di
feature e potenzialità a qualunque altra libreria o framework attualmente disponibile sul
mercato (e cito ad es. React o Vue).
L’argomento “Form” è davvero molto ampio e in questo articolo analizzeremo velocemente solo
una piccola parte delle funzionalità dei template-driven form.
Salvando il file e provando il form riceveremo degli errori perché non abbiamo ancora
implementato i metodi save() e reset().
Il form non è ancora completo ma di seguito descrivo alcune delle funzionalità utilizzate finora:
Il form sarà utilizzato sia per gestire l’inserimento di nuovi elementi, che la modifica di
quelli esistenti
Al submit del form (tramite click o pressione del pulsante INVIO della tastiera) sarà
invocato il metodo submit(f) tramite il quale passiamo anche una reference del form
Il pulsante per il submit sarà disabilito fino a che tutti i campi di input del form non saranno
validi. In questo esempio abbiamo specificato che la label è un elemento required perciò
il form non sarà valido fino a che quel campo (ed eventuali altri) non sarà valido
La label del pulsante submit assumerà il valore SAVE, nel momento in cui abbiamo un
elemento selezionato, oppure ADD quando invece ne inseriremo uno nuovo
Il pulsante reset invece si occuperà di deselezionare l’elemento attivo, per permettere la
creazione di un nuovo elemento
Revoca cookie
Completiamo la demo aggiungendo i metodi per la gestione dell’inserimento e modifica di
elementi e integrando, nel template HTML, i campi di input e una select per la gestione di alcune
delle proprietà dei device (prezzo e sistema operativo)
app.component.js
app.component.html
Risultato:
In fase di editing:
Revoca cookie
In fase di inserimento:
Revoca cookie
Next Step
Questo articolo introduce solo una minima parte delle funzionalità del framework e non
vengono applicate tutta una serie di best practices e metodologie indispensabili per rendere
l’applicazione più scalabile, manutenibile e testabile.
Il framework include, infattim moltissimi altri strumenti tra i quali:
La possibilità di suddividere il codice in componenti e creare quindi custom HTML tags (ad
es. )
Suddividere la business logic in servizi utilizzando il motore di dependency injection
integrato
Organizzare il progetto in diverse route e in moduli custom
Creare custom directives e custom pipes
Gestire autenticazione (ad es. JWT o OAuth), integrare interceptor ecc. Revoca cookie
Utilizzare facilmente pattern architetturali per la gestione dello stato applicativo come
Redux o MobxState Tree, già citati in precedenza
e molto molto altro
Ad esempio, l’esercizio precedente, in un contesto reale, potrebbe essere scritto come segue, e
questo è solo uno dei possibili approcci che non utilizza neppure uno dei pattern architetturali
menzionati sopra:
1 @Component({
2 selector: 'devices-view',
3 template: `
4
5 <toggable [title]="Device Form">
6 <add-edit-form
7 [active]="store.active"
8 (reset)="actions.reset()"
9 (save)="actions.save($event)">
10 </add-edit-form>
11 </toggable>
12
13 <toggable title="DEVICES" [closable]="false">
14
15 <list-filter
16 class="header-content"
17 [filters]="filters"
18 (update)="this.filters = $event"></list-filter>
19
20 <devices-list
21 [devices]="store.devices"
22 [active]="store.active"
23 [filters]="filters"
24 (selectRow)="setActive($event)"
25 (delete)="actions.delete($event)"></devices-list>
26 </toggable>
27 `
28 })
29 export class DevicesViewComponent {
30 constructor(
31 public store: DeviceStore,
32 public actions: DeviceService,
33 ) {
34 // Load devices
35 this.actions.getAll();
36 }
37
38 }
Revoca cookie
Lo stesso discorso vale per la struttura del progetto che, al crescere della complessità,
naturalmente dovrà essere organizzato diversamente. Un esempio:
DEMO
Di seguito una demo live. Tieni presente che il server Node utilizzato è un hosting gratuito.
Potrebbe non essere velocissimo (soprattutto in fase di avvio) e non mi ritengo responsabile dei
contenuti inseriti dagli altri utenti 😉
Revoca cookie
devices.component.ts × https:/…
1 import { Component, ElementRe
2 import { Device } from '../..
3 import { HttpClient } from '@a
4 import { NgForm } from '@angul
Phone model *
5
6 const INITIAL_STATE = { label
7 Price *
8 @Component({
9 selector: 'devices-view', Select OS *
10 template: `
11 <br>
12 <div class="card bg-dark t Rate: 1 2
13 <!--edit / add form-->
14 <form novalidate
15 (submit)="save(f) description (not requir
16 #f="ngForm"
17 class="card-body">
18
ADD
19 <input type="text"
20 [ngModel]="acti
21 name="label"
22 required
23 class="form-con 1 1
Console
24 placeholder="Ph
angular5-bootstrap4-crud-device-list-simple Editor Preview Both
CONCLUSIONE
Share on...
19 Comments
Grazie mille. Nel mio canale YouTube trovi anche delle playlist di video con altri
argomenti (custom components, providers, form, custom validators, ecc. ) ma non
ne vado molto fiero perché registrati in fretta, oltre al fatto che produrre video non è
il mio forte 🙂
*ngFor=”let d of devices”
mentre dovrebbe essere *ngFor=”let device of devices” come negli altri listati.
Ringrazio
(click)=”setActive(d)
dovrebbe essere
(click)=”setActive(device)
in quanto ngFor è :
Ringrazio.
Grazie mille per i due suggerimenti Gianni. Hai perfettamente ragione e ho corretto
gli errori.
Revoca cookie
Sono errori di battitura in quanto nel mio esempio live ho usato la “d” per essere
più conciso (pur essendo una bad practice) ma durante la stesura dell’articolo l’ho
sostituito con “device” dimenticando i due esempi da te citati. Gentilissimo 🙂
“`
npm i bootstrap[AT]4.0.0 font-awesome[AT]4.7.0
npm WARN [AT]angular-devkit/schematics[AT]0.0.52 requires a peer of [AT]angular-
devkit/core[AT]0.0.29 but none is installed. You must install peer dependencies yourself.
npm WARN [AT]schematics/angular[AT]0.1.17 requires a peer of [AT]angular-
devkit/core[AT]0.0.29 but none is installed. You must install peer dependencies yourself.
npm WARN ajv-keywords[AT]3.1.0 requires a peer of ajv[AT]^6.0.0 but none is installed.
You must install peer dependencies yourself.
npm WARN bootstrap[AT]4.0.0 requires a peer of jquery[AT]1.9.1 – 3 but none is
installed. You must install peer dependencies yourself.
npm WARN bootstrap[AT]4.0.0 requires a peer of popper.js[AT]^1.12.9 but none is
installed. You must install peer dependencies yourself.
“`
Oltre a questo, aggiornate le dipendenze come da errore,
a `npm start`
ho
““
ERROR in ./node_modules/css-loader?
{“sourceMap”:false,”importLoaders”:1}!./node_modules/postcss-loader/lib?
{“ident”:”postcss”,”sourceMap”:false}!./node_modules/bootstrap/dist/css/bootstrap.min.css
Module build failed: BrowserslistError: Unknown browser major
“`
per risolvere ho aggiornato a `angular-cli[AT]1.7.x` come da questa issue
https://github.com/angular/angular-cli/issues/9288#issuecomment-360430754.
Ciao, dove posso trovare le slide che sono state mostrate all’evento angular best
practises?
Ciao Fabio, ho notato che prendi i dati nel costruttore piuttosto che all’interno della
funzione ngOnInit. A cosa è dovuta questa scelta ? Grazie 🙂
Grazie! Tutorial fatto benissimo per i primi passi con Angular. Molto utile!
Fabio da poco sto iniziando ad interessarmi al mondo angular, node.js, non mi è chiara
una cosa:
con php pubblicavo su altervista i miei siti di test in modo gratuito , in questo caso si
trovano hosting gratuiti dove pubblicare i miei test?
se si potresti indicarmene almeno uno?
grazie la guida è chiara e precisa
Ciao Emanuele, a meno che non usi Server Side Rendering in Angular (e
inizialmente ne dubito), le tue applicazioni Angular / React utilizzeranno
esclusivamente di API RESTful.
In questo specifico contesto (il più comune) è su iciente che tu faccia una build
(npm run build), verrà creata una versione statica del sito (HTML + JS ES5) e il
risultato potrà quindi girare su un qualunque webserver (Apache, IIS, NGinx,Revoca
ecc). cookie
Lato server, le tuoi API le puoi mettere anche su un’altro server e fruirle dalla tua
app (purché sia abilitato CORS sul server).
Se hai altri dubbi o domande ti consiglio di frequentare il nostro gruppo Facebook
Angular Developer Italiani
BRAVO
Leave A Comment
Comment...
POST COMMENT
LINK UTILI
Deploy di un’applicazione
NodeJS su Azure con
Corsi di Formazione
Visual Studio Code
About Me
Deploy di un sito statico su
Azure (storage) con Visual Iscriviti alla Newsletter
Studio Code Revoca cookie
Typescript 3.8 & ESNext
private fields
(this.#myProp)
2019 Fabio Biondi - All Rights Reserved - P.I. 01116230317 - Privacy Policy
Revoca cookie