Immagine descrittiva del post

In questo articolo riassumerò alcuni concetti base del framework Angular in un esempio di applicazione Angular completo che svilupperemo passo passo.

 

Prerequisiti

Prima di iniziare, ecco alcuni requisiti per lo svolgimento del tutorial di questo post. Naturalmente occorre avere installato Angular (v 8) e Angular CLI, quest’ultimo, servirà per generare le varie “parti” dell’applicazione utilizzando il terminale. Consiglio inoltre Visual Studio Code come ambiente di sviluppo per applicazioni Angular.

 

Creare una nuova applicazione Angular

Abbiamo già visto come creare una nuova applicazione Angular, daremo all’esempio il nome DemoTextApp, simulando un’applicazione in grado di creare e organizzare messaggi di testo. Scegliamo di utilizzare Angular routing e SCSS come stile.

ng new DemoTextApp

Apriamo l’app creata in Visual Studio Code per poterla modificare.

 

Utilizzare Angular Material

Per rendere l’interfaccia gradevole faremo uso di Angular Material, che comprende già un allestimento di componenti. Quello che faremo è aggiungere questi componenti ai nostri template facendo riferimento alla documentazione.

Aggiungere il modulo Material

Aggiungiamo Angular Material al progetto scegliendo, tra le opzioni, il tema Indigo/Pink e di usare HammerJS e browser animation.

ng add @angular/material

Creiamo ora un modulo dedicato material attraverso il quale condivideremo i singoli moduli della libreria con i moduli dell’applicazione.

ng g module shared/modules/material --flat

Con il comando precedente abbiamo creato il file material.module.ts all’interno delle cartelle shared/modules, indicando con l’opzione –flat di non voler creare un’ulteriore cartella material contenente il modulo.

nota: tutti i file generati con il comando ng generate .. (abbreviato ng g) verranno inseriti all’interno della cartella app, a meno dell’utilizzo di opzioni – documentazione.

Importiamo il file material.module.ts all’interno di app.module.ts (imports) per poterlo utilizzare, lo modificheremo all’occorrenza.

Codice di esempio
app.module.ts
 

Aggiungere le pagine principali

Anche se l’app che andremo a creare sarà di modeste dimensioni, per completezza, faremo uso del pattern Lazy Loading. Questo permette il caricamento degli NgModules al loro bisogno, utile appunto per applicazioni di grandi dimensioni con molti percorsi.

 

Pagina Main

Creiamo subito il modulo e il componente Main come punto di ingresso dell’applicazione, dopodiché creeremo il modulo e il componente Home all’interno del quale andremo a gestire i messaggi.

ng g module main --routing=true 
ng g c main

Il primo comando genera all’interno della cartella main il file main.module.ts e, con l’opzione –routing=true, il file main-routing.module.ts automaticamente aggiunto a MainModule come imports. In MainRoutingModule andremo a configurare le rotte che vogliamo utilizzare.

Subito dopo aver eseguito il primo comando possiamo lanciare il secondo, con la quale andremo a creare i componenti per il Main. In automatico verrà aggiunto MainComponent alle dichiarazioni (declarations) di MainModule.

Il modulo Main appena creato ci servirà per gestire le pagine che effettivamente vogliamo andare ad utilizzare, Home e Message. Sembra una cosa un pò macchinosa, ma questo ci permette di svincolarci dall’utilizzare il modulo base app, che invece vogliamo che rimanga il più pulito possibile.

Come prima cosa puliamo il file app.component.html sostituendo il contenuto con l’unica direttiva .

La stessa cosa andremo a fare per il file main.component.html, poiché non ci interessa il contenuto di MainComponent ma piuttosto vogliamo visualizzare i contenuti delle pagine che andrà a gestire.

 

Creare le pagine Home e Message

Come fatto per Main, andiamo a creare il modulo e i relativi componenti per Home e Message.

ng g module home --routing=true
ng g c home

ng g module message --routing=true
ng g c message
 

Configurare le rotte per le pagine dell'applicazione Angular

A questo punto dobbiamo configurare il caricamento dei vari moduli definendo il comportamento dell’applicazione.

Il componente Main è il primo che vogliamo caricare all’avvio dell’applicazione. Main deve essere configurato per gestire le pagine Home e Message. Aggiungiamolo alle rotte del modulo AppRouting nel file app-routing.module.ts come in figura.

Codice di esempio
app-routing.module.ts

Successivamente, andiamo a configurare il file main-routing.module.ts definendo le rotte per il caricamento dei moduli Home e Message. In questo esempio, assegneremo alle pagine Home e Message rispettivamente le path “home” e “message”.

Poiché la pagina Home dovrà rappresentare la nostra pagina principale, aggiungiamo un redirect a questa quando la path base “/” viene chiamata.

Codice di esempio
main-routing.module.ts

Ora, dobbiamo configurare le rotte delle pagine affinché queste mostrino il contenuto dei componenti al caricamento del modulo. Modifichiamo le rotte di entrambi, Home e Message, nei corrispettivi file di routing.

 
 

Creare un ambiente di Storage per l'applicazione Angular

Poco fa, abbiamo aggiunto e configurato le  pagine Home e Message, affinché mostrino il proprio contenuto. In particolare, la pagina message deve mostrare una lista dei messaggi aggiunti.

Da dove prendiamo la lista di messaggi?

Cerchiamo di creare un ambiente di persistenza (nel caso reale di un’applicazione web con architettura RESTful, il compito viene svolto da un back-end) tramite il quale possiamo salvare i messaggi per poi poterli recuperare. Per semplicità, in questo esempio, non useremo un database, ma andremo a salvare i dati direttamente nel browser tramite l’oggetto localStorage.

Andiamo quindi a definire una classe service da utilizzare come interfaccia per la comunicazione con localStorage. Andremo ad inserire uno StoreService all’interno della cartella shared del progetto, dato che questo deve essere condiviso con gli altri componenti, creando una nuova cartella services.

ng g service shared/services/store

Apriamo il file store.service.ts appena creato e implementiamo i metodi che serviranno per salvare e recuperare i dati all’interno dell’oggetto localStorage.

Codice di esempio
store.service.ts

Con il metodo save cosi definito, assumiamo di voler salvare una stringa come tipo di dato. Questo perché l’oggetto localStorage è in grado di gestire esclusivamente stringhe da associare ad una certa chiave come una coppia chiave-valore.

 

Definire la struttura di un messaggio

Quando parliamo di messaggio, ci riferiamo ad un nuovo oggetto composto da più campi, tra i quali un messaggio di testo.

Creiamo una classe Message come modello di dato definita all’interno di un nuovo file message.ts da posizionare in una nuova cartella model all’interno di shared. Cosi come per il modulo Material, una classe riguardante il modello dei dati deve poter essere condivisa con gli altri componenti.

ng g class shared/model/message
Codice di esempio
message.ts

Il nostro tipo di dato sarà composto dai campi:

  • id: identificativo dato dal timestamp della creazione
  • title: stringa contenente il titolo
  • message: stringa contenete il messaggio
  • expirationDate: data di scadenza del messaggio
 

Creare un componente Service di un'applicazione Angular

Un Service in un’applicazione Angular è in genere una classe con uno scopo ristretto e ben definito. Dovrebbe fare qualcosa di specifico e farlo bene.

Nel nostro esempio, creiamo ora una classe MessageService per gestire i messaggi.

ng g service message/message

Apriamo il file message.service.ts e definiamo i metodi che andremo ad utilizzare per la gestione dei messaggi, in particolare:

  • save: aggiunge un nuovo messaggio
  • getAll: recupera la lista completa
  • delete: rimuove un messaggio dalla lista
Codice di esempio
message.service.ts
 

Definire le pagine dell'applicazione

Arrivati a questo punto, andiamo a comporre le pagine della nostra applicazione Angular utilizzando componenti Material.

 

La pagina Message

La pagina message dovrà contenere una lista di messaggi e alcuni pulsanti per l’aggiunta e la rimozione di questi dalla lista.

Apriamo il file material.module.ts e importiamo (imports) e esportiamo (exports) il modulo MatListModule per la visualizzazione della lista.

Importiamo il modulo MaterialModule all’interno del modulo MessageModule (dentro imports) per poterlo utilizzare.

Modifichiamo il file message.component.html inserendo il nuovo componente.

Codice di esempio
message.component.html

La lista viene popolata leggendo la variabile messages$, e facendo uso di AsyncPipe (*ngFor=”let message of messages%%EDITORCONTENT%%nbsp;| async”). Nel caso in cui non sono presenti messaggi viene mostrato il messaggio “No messages yet”.

Dobbiamo inizializzare la variabile all’attivazione del componente e lo facciamo richiamando il metodo getAll di MessageService creato appositamente. Questo metodo, infatti, ha come valore di ritorno un Observable contenente un array di oggetti Message.

Codice di esempio
message.component.ts
 

Definire le operazioni di salvataggio e cancellazione dei messaggi

Procediamo con l’implementazione delle funzionalità della pagina message aggiungendo la possibilità di salvare un nuovo messaggio e cancellarne uno già presente nella lista.

 

Aggiungere un nuovo messaggio

Solitamente, l’aggiunta di un nuovo oggetto avviene tramite l’inserimento delle informazioni in un form. In questo esempio, per semplicità, creeremo un oggetto standard ogni volta che viene premuto l’apposito pulsante.

Aggiungiamo il metodo add in MessageComponent nel file message.component.ts. Questo si occuperà di passare le informazioni al MessageService che salverà il messaggio nello Storage, e successivamente, ricaricherà la lista (initData).

Codice di esempio
message.component.ts

Aggiungiamo quindi il codice HTML al file message.component.html implementando un pulsante che, al click, andrà a chiamare il metodo precedente passandogli le informazioni.

Codice di esempio
message.component.html

Modifichiamo l’aspetto della pagina aggiungendo la classe primary-buttons-row, cosi da posizionare i pulsanti specificati all’interno del div nella posizione in basso a destra della schermata. Per questo, apriamo il file message.component.scss e definiamo la classe di stile come nell’immagine sottostante.

Codice di esempio
message.component.scss
 

Cancellare un messaggio dalla lista

Avendo una rappresentazione a lista, possiamo inserire un pulsante a icona all’interno della riga corrispondente al messaggio. In questo modo abbiamo sufficienti informazioni per identificare un messaggio, come appunto il suo id. Sfruttiamo questa informazione per definire un metodo per la cancellazione dell’elemento.

Codice di esempio
message.component.ts

Entrambi i metodi add e delete, dopo la loro esecuzione (subscribe), devono chiamare il metodo initData, in modo da fare un refresh della lista.

Possiamo ora modificare il template inserendo il pulsante di cancellazione.

Codice di esempio
message.component.html

Siccome stiamo utilizzando altri componenti Material, quali button e icon, dobbiamo importare i rispettivi moduli in MaterialModule, come visto prima per MatListModule.

Codice di esempio
material.module.ts
 

Navigare tra le pagine di un'applicazione Angular

La navigazione in un’applicazione Angular è simile alla navigazione in un browser: inserisci un URL nella barra degli indirizzi, oppure, fai click sui collegamenti della pagina e il browser passa a una pagina corrispondente.

Angular Router sfrutta questo modello: può interpretare un URL del browser, eventualmente con parametri, come un’istruzione per passare a una vista associata generata dal client.

Come ultimo step, realizziamo una comunicazione diretta tra le due pagine (Home e Message) aggiungendo altri pulsanti.

Utilizzeremo la direttiva routerLink in tag anchor <a> per la navigazione.

Dalla pagina message vogliamo poter navigare verso la pagina home, e viceversa. Partendo da message, inseriamo il nuovo pulsante dentro il contenitore (primary-buttons-row) definito prima.

Codice di esempio
message.component.html

Aggiungiamo, come per MessageModule, il modulo MaterialModule tra gli imports di HomeModule, e andiamo a modificare la pagina home.

Creiamo un template adatto inserendo un contenitore in posizione centrale con al suo interno una breve descrizione dell’applicazione e un pulsante per accedere alla lista. Sostituiamo quindi il contenuto di home.component.html come in figura.

Codice di esempio
home.component.html
Codice di esempio
home.component.scss
 

Sei riuscito a seguirmi fino adesso?

Manca poco, non mollare proprio ora. Tra poco termineremo l’esempio andando a creare un’ulteriore pagina per visualizzare i dettagli del messaggio.

 

Creare una pagina di dettaglio

Andiamo ora a definire una nuova pagina per la visualizzazione del dettaglio di un messaggio, alla quale si accede facendo click sull’elemento della lista, o meglio, su un nuovo pulsante corrispondente all’elemento della lista.

Creiamo, come visto per le altre pagine, un nuovo modulo MessageDetailsModule e, successivamente, il componenti message-details.

ng g module message-details --routing=true 
ng g c message-details

Lasciamo per il momento in sospeso la pagina message-details, e andiamo a creare un’ulteriore pagina message-list. Questo perché andremo ad utilizzare la vecchia pagina message come punto d’ingresso per le varie viste dei messaggi: il dettaglio di un messaggio e la lista. Quest’ultima, è la stessa che abbiamo definito all’interno di message e che la sostituiremo con message-list.

ng g module message-list --routing=true 
ng g c message-list

Come appena detto, spostiamo il contenuto di message.component.html nel file message-list.component.html sostituendolo con la sola direttiva . Sostituiamo anche il contenuto di message.component.ts all’interno di message-list.component.ts, affinché la vista si comporti come in precedenza.

Importiamo il modulo MaterialModule in MessageListModule.

Andiamo ora a definire il comportamento delle rotte modificando i file interessati message-routing.module.ts e message-list-routing.module.ts.

 

Aggiungiamo ora alla lista il pulsante che ci permetterà di accedere alla pagina di dettaglio del messaggio, modificando anche l’aspetto della lista inserendo un divisore tra gli elementi.

Screenshot di esempio
Pagina MessageList

Cliccando sul nuovo pulsante vogliamo visualizzare i dettagli del messaggio. Abbiamo inserito la direttiva routerLink al pulsante per permettere la navigazione verso la nuova rotta. Da sottolineare il fatto di aver aggiunto le parentesi quadre ( [routerLink]=”message.id” ) poiché vogliamo passare un valore, l’id del messaggio, come parametro.

Definiamo quindi la nuova rotta aggiornando i file message-routing.module.ts e message-details-routing.module.ts.

 

La pagina dettaglio di un messaggio

A questo punto non resta che aggiornare il componente message-details per la visualizzazione dei dettagli del messaggio.

Utilizziamo il componente mat-card di Material in modo da rendere la vista più gradevole. Aggiungiamo quindi il modulo MatCardModule tra gli imports e exports del modulo MaterialModule e importiamo quest’ultimo in MessageDetailsModule per poterlo utilizzare.

Modifichiamo il template html in questo modo:

Codice di esempio
message-details.component.html

Dobbiamo ora implementare il recupero del messaggio con un metodo da aggiungere alla classe service, per poi renderlo disponibile alla vista.

Creiamo all’interno di MessageService il metodo get che riceve come parametro l’id del messaggio utilizzato per recuperare questo dalla lista.

Codice di esempio
message.service.ts

Implementiamo la classe MessageDetailsComponent per inizializzare la variabile message estraendo l’id passato dalla URL. Per fare questo, utilizzeremo l’oggetto ActivatedRoute di @angular/router.

Codice di esempio
message-details.component.ts

Per finire, aggiungiamo un pulsante delete tra le azioni disponibili, in modo da poter cancellare il messaggio direttamente dalla sua visualizzazione. Implementiamo anche il metodo delete che esegue l’operazione di cancellazione e riporta alla lista.

Il metodo delete, come lo abbiamo definito, riceve come parametro l’id del messaggio e chiama il metodo delete di MessageService già utilizzato in precedenza. Successivamente, al completamento dell’operazione di cancellazione del messaggio, utilizziamo l’oggetto Router, sempre di @angular/router, per tornare alla pagina della lista.

La pagina risultante sarà quella mostrata in figura.

Screenshot di esempio
Pagina dettaglio messaggio
 

E ora?

Arrivati a questo punto, l’applicazione è completa e pronta per essere testata nel suo insieme. Apriamo la finestra del browser alla pagina http://localhost:4200 e iniziamo ad usare la nostra applicazione di messaggi.

Spero che quello che hai letto sia stato piacevole e soprattutto utile.

Devo chiederti un favore. Per ringraziarmi del tempo che ho speso e dell’impegno che ho messo nel realizzare l’esempio, puoi condividere questo articolo con altri, per far si che risulti utile anche a loro. È un piccolo sforzo per te e sarebbe veramente grande per me.

Per ringraziarti, ho reso disponibile tutto il codice dell’esempio su GitHub a questo indirizzo, puoi farne tutto l’uso che vorrai.

Recommended Posts

3 Comments

  1. Grazie a te Alessandro, questo mi permetter? di confrontare per intero il codice con quello che ho riscritto io e allinearmi con l’ottimo tutorial che hai pubblicato.

  2. Buongiorno sono andato a vedere nel GitHub segnalato, ma purtroppo mi sembra che sia stata pubblicata solo la generazione standard di Angular-Cli e non il progetto completo. E’ corretto ?

    • Buongiorno, hai perfettamente ragione.
      Ho aggiornato il repository e ora lo dovresti vedere.
      Grazie per il feedback. Ciao


Add a Comment

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *