Tempo di lettura: 12 minuti
In questo tutorial vedremo come realizzare un’applicazione Angular con Firebase, andremo a compilare una web App CRUD.
Per CRUD si intende ‘CREATE READ UPDATE DELETE‘ ossia ‘CREA LEGGI AGGIORNA CANCELLA‘ che sta alla base delle azioni da compiere con un database relazionale. Anche se ci saranno delle query complesse alla fine tutto si riduce a queste quattro azioni fondamentali.
Firebase è un sistema su Cloud di proprietà di Google completo di hook API ,spazio di archiviazione file,sistema di autenticazione e funzionalità di Hosting, è molto semplice da configurare ed utilizzare.
Strumenti necessari per creare un’applicazione Angular con Firebase
Prima di poter procedere dobbiamo necessariamente scaricare alcuni strumenti fondamentali:
- Node.js (versione consigliata)
- Angular (ultima versione)
- Angular-cli (ultima versione)
- Firebase
- Git Bash (per utenti window o Mac)
- Ide (io consiglio Visual studio)
Una volta scaricato ed installato Node.js verifica che tutto sia andato per il verso giusto, apri il prompt dei comandi e digita : node -v e npm -v
se il risultato è il seguente:
PS C:\Users\lucio\Desktop\> node -v v10.15.3 PS C:\Users\lucio\Desktop\> npm -v 6.4.1
è tutto a posto, cioè queste sono le versioni attuali di NODE e NPM.
Se vuoi saperne di più puoi andare a leggerti una guida che avevo realizzato un po di tempo fa.
Applicazione Angular con Firebase: cosa realizzeremo
Nel corso del tutorial andremo a realizzare Art Coffee, ossia un’applicazione atta ad ordinare il caffè in cui è possibile aggiungere ordini (quindi creare), elencare gli ordini dal database(leggere), aggiornare un ordine e rimuovere un ordine.
Lo scopo della guida è quello di farti capire come funziona Firebase Firestore e come sia facile l’integrazione di Angular con questo.
Installare il database Firebase Firestore
La configurazione di Google Firebase è piuttosto semplice. Aprite il browser e collegatevi su Google Firebase Console, loggatevi con il vostro account Google ( se non lo avete dovete crearlo).
Quindi cliccate su CREA PROGETTO , chiamatelo come volete (in questa guida lo chiameremo Art Coffee), alla fine verrete reindirizzati alla pagina seguente:
ora cliccate su sviluppo > database, verrete reindirizzati alla seguente pagina:
quindi fate click su crea database, comparirà un finestra tipo questa:
scegli ‘avvia in modalità di prova‘ e quindi clicca su Avanti, ora scegli la località (la nostra eur3 (europe-west)).
Ora fai click su PROJECT OVERVIEW come in figura:
quindi cliccate su come in figura sotto:
ora non vi resta che registrare l’app.
Installiamo Angular-cli e creiamo l’applicazione angular
Per installare ANGULAR-CLI da terminale digita:
npm install -g @angular/cli
se utilizzi linux:
sudo npm install -g @angular/cli
se vuoi saperne di più su Angular-Cli leggi la guida.
Ora siamo pronti per creare la nostra applicazione, create una cartella con nome AngularFirebase e da terminale dirigetevi all’interno di essa( vi ricordo che se utilizzate Visual Studio potete digitare i tasti ctrl+ò per aprire il terminale) quindi digitate:
ng new artCoffee
attendete qualche istante ,una volta creata, spostatevi su di questa , sempre da terminale digitando:
cd artCoffee
avviate il server digitando:
ng serve --open
Inserendo ‘–open’ la finestra del browser si apre automaticamente:
Applicazione Angular con Firebase:realiziamo i componenti dell’App
Per la nostra applicazione andremo a creare solamente 2 componenti ed un service: orders, order-list e quindi il service shared/order. Quindi sempre dall’interno della directory del progetto, aprite il terminale e digitate:
ng g c orders
quindi
ng g c order-list
ed infine
ng g s service/orders
Quest’ultimo creerà il service all’interno della cartella service.
Aggiungere lo stile
In questa guida andremo ad utilizzare il framework Materialize, ma sei liberissimo di usarne un altro a tuo piacimento , tipo Bootstrap.
Inoltre utilizzeremo le icone Material di Google, ma anche in questo caso a te la scelta.
Implementeremo sia le icone che lo stile mediante cdn (solo per velocizzare le spiegazioni). Aprite il file index.html della vostra applicazione ed incollate prima della chiusura del tag head:
<! - CSS materializzato compilato e minimizzato -> <link rel = "stylesheet" href = "https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css" > <! - Materialise JavaScript compilato e minimizzato -> <script src = "https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"> </ script > <! - Icone materiali di Google -> <link href = "https://fonts.googleapis.com/icon?family=Material+Icons" rel = "stylesheet" />
Modifichiamo l’App component
Aprite app.component.html ed eliminate tutto il codice presente in esso, quindi inserite:
<div class="container"> <divclass="row"> <app-orders class="col s6"></app-orders> <app-order-list class="col s6"></app-order-list> </div> </div>
Come potete notare i nomi delle classi sono simili a quelle utilizzate in bootstrap.
Impostiamo il Form
Aprite il file App.Module.ts ed importate il modulo ReactiveFormsModule:
import { ReactiveFormsModule } from '@angular/forms';
dopo di che aggiungetelo nelle imports:
imports: [ ..., ReactiveFormsModule, ... ],
Se volete approfondire una panoramica sulle differenze fra Reactive Form e Template Driven potete leggere questo articolo.
Ora aprite il service ed importiamo FormControl e FormGroup da @angular/forms:
import { FormControl, FormGroup } from "@angular/forms"; ... ...export class OrdersService { constructor() {} form = new FormGroup({ customerName: new FormControl(''), orderNumber: new FormControl(''), coffeeOrder: new FormControl(''), completed: new FormControl(false) }) }
quindi instanzia form in cui imposteremo le proprietà del modulo.
Utilizzare il FormModule all’interno dei nostri componenti
Aprite il file orders.component.ts ed ,innanzitutto, importate il service:
... import { OrdersService } from '../service/orders.service'; @Component({ selector: 'app-orders', templateUrl: './orders.component.html', styleUrls: ['./orders.component.scss'] }) export class OrdersComponent implements OnInit { constructor(privateServiceOrder:OrdersService){} ...
quindi iniettatelo all’interno del costruttore.
Aprite il file orders.comonents.html ed inserite le seguenti righe:
<form [formGroup]="this.ordersService.form"> <inputplaceholder="Order Number"formControlName="orderNumber"type="text"class="input-field col s12"> <inputplaceholder="Nome cliente"formControlName="customerName"type="text"class="input-field col s12"> </form>
Avremo il nostro form associato alle variabili inserite nella relativa classe (orders.components.ts).
Nel file orders.components.ts andremo a creare un Array di dati contenete i tipi di caffè ordinabili anche se in realtà avrei potuto delegare tale compito al database creandolo dinamicamente. Per velocizzare la guida lo faremo staticamente con dei dati finti:
coffees = ["Americano", "Flat White", "Cappuccino", "Latte", "Espresso", "Machiato", "Mocha", "Hot Chocolate", "Tea"];
Ora per visualizzare l’elenco dei caffè disponibili inserite le seguenti righe appena sotto l’apertura del tag form in orders.components.html:
<buttonclass="waves-effect waves-light btn col s4"*ngFor="let coffee of coffees"(click)="addCoffee (coffee)"> {{coffee}} </button> <ulclass="collection "> <li*ngFor=" let coffee of coffeeOrder "> <spanclass=" col s11 "> {{coffee}} </span> <aclass=" col s1 "(click)=" removeCoffee (coffee) "> x </a> </li> </ul>
Riaprite il file orders.components.ts , quindi realizzeremo un array vuoto che ospiti l’ordine del caffè, creeremo, inoltre, la funzione addCoffe() per aggiungere nuovi caffè e removeCoffee() per eliminare questi dall’ordine:
coffeeOrder = []; addCoffee=coffee=>this.coffeeOrder.push(coffee); removeCoffee=coffee=>{ constindex=this.coffeeOrder.indexOf(coffee); if(index >-1){this.coffeeOrder.splice(index,1);} }
Gestione dell’invio del modulo
Aprite il file orders.components.html, posizionatevi nella parte inferiore del form ed aggiungete il button , il quale gestirà l’invio delle info nel database:
<form [formGroup]="this.ServiceOrder.form" (ngSubmit) = 'onSubmit()'> ...
<button class="waves-effect waves-light btn col s12" (click)="onSubmit()"> Submit </button>
Impostare il componente order-list
Intanto aprite il file order-list.component.html e realizzate una tabella atta a contenere i valori estratti dal db non che le funzionalità che serviranno per indicare l’ordine effettuato o rimuovere lo stesso:
<table> <thead> <tr> <th>Order No.</th> <th>Name</th> <th>Coffee List</th> </tr> </thead> <tbody> <tr> <td> </td> <td></td> <td> </td> <td> <iclass="material-icons">check</i> </td> <td> <iclass="material-icons">delete_forever</i> </td> </tr> </tbody> </table>
Collegare il database Firebase Firestore ad Angular
Per poter connettere l’applicazione Angular al databse Firebase bisogna innanzitutto installare il pacchetti firebase è @angular/fire i quali ti consentiranno di accedere a AngularFireModule
e AngularFirestoreModule:
npm i --save firebase @angular/fire
Quindi aprite la console Firebase dove copieremo i dettagli di configurazione da utilizzare nella nostra applicazione Angular:
fate click su project overview > Impostazioni progetto:
nella pagina che segue fai check su Configurazione quindi copia il file di configurazione.
Ora aprite il file enviroments.ts ed incollate il codice precedente:
export const environment = { production: false, firebaseConfig: { apiKey: "xxx", authDomain: "xxxx.firebaseapp.com", databaseURL: "https://xxxx.firebaseio.com", projectId: "xxxx", storageBucket: "xxxx.appspot.com", messagingSenderId: "xxxxx" } };
Aprite il file app.module.ts ed ,innanzitutto,imporate i pacchetti installati in precedenza, quindi aggiungeteli su imports:
import { environment } from "../environments/environment"; import { AngularFireModule } from "@angular/fire"; import { AngularFirestoreModule } from "@angular/fire/firestore"; ... @NgModule({ ... imports: [ ... AngularFireModule.initializeApp(environment.firebaseConfig), AngularFirestoreModule ] ... })
Importa Firestore nel Service
Apri orders.service.ts ed importa AngularFirestore:
... import { AngularFirestore } from '@angular/fire/firestore';
@Injectable({ providedIn: 'root' }) export class OrdersService { constructor(privatefirestore:AngularFirestore){} ...
Finalmente siamo pronti per iniziare a lavorare sul ‘CRUD’ della guida.
Aggiungi il record (CREATE)
Aprite il service orders e aggiungiamo il metodo Add(). Qui bisogna specificare anche il nome della collection (tabella) alla quale andranno inviati i dati:
/*Metodo add*/ createCoffeeOrder(data){ returnnewPromise<any>((resolve,reject)=>{ this.firestore .collection('coffeeOrders') .add(data) .then(res=>{},err=>reject(err)); }); }
Quindi aprite il componente orders e create la funzione onSubmit() che andrà a richiamare la precedente funzione:
onSubmit(){ this.ServiceOrder.form.value.coffeeOrder =this.coffeeOrder; constdata=this.ServiceOrder.form.value; this.ServiceOrder.createCoffeeOrder(data) .then(res=>{ /*do something here.... maybe clear the form or give a success message*/ }); }
se aprite la console di Firebase noterete che abbiamo appena creato una colection.
Leggi i record (READ)
Aprite di nuovo il service e aggiungiamo la funzione di lettura che chiameremo getCoffeOrders():
getCoffeeOrders(){ return this.firestore.collection('coffeeOrders').snapshotChanges(); }
Ora aprite il file order-list.component.ts e aggiungete la funzione atta a richiamare quella del service, non prima di averlo importato in esso ed averlo iniettato all’interno del costruttore:
...
import { OrdersService } from '../service/orders.service'; @Component({ selector: 'app-order-list', templateUrl: './order-list.component.html', styleUrls: ['./order-list.component.scss'] }) export class OrderList Component implements OnInit { constructor(private orderService:OrdersService){} ...
Quindi create la funzione per ottenere i risultati del record ed inizializzatela in ngOnInit():
...
coffeeOrders; ngOnInit(){this.getCoffeeOrders();} getCoffeeOrders=()=> this.serviceOrder .getCoffeeOrders() .subscribe(res=>this.coffeeOrders = res) ...
come avrete di certo notato ho anche creato la proprietà coffeOrders la quale mapperà i risultati dal database tramite un subscribe().
In fine apri order-list.html ed aggiungi la direttiva *ngFor al tag tr per ciclare i risultati:
...
<tbody> <tr*ngFor="let order of coffeeOrders"> <td>{{ order.payload.doc.data().orderNumber }}</td> <td>{{ order.payload.doc.data().customerName }}</td> <td><span*ngFor="let coffee of order.payload.doc.data().coffeeOrder"> {{ coffee }} </span> ...
Aggiorniamo i dati (UPDATE)
Ora andremo a vedere come aggiornare i dati su Firestore supponendo di voler contrassegnare un ordine come completo. Aprite il file order-list e aggiungete un evento click all’icona del flag con relativo metodo:
...
<td[hidden]="order.payload.doc.data().completed"(click)="markCompleted(order)"> <iclass="material-icons">check</i> </td> ...
Come vedete ho impostato un attributo hidden al tag td in quanto sarò in grado di determinare in modo dinamico se visualizzare o meno l’icona, difatti se vi ricordate abbiamo impostato a false il valore relativo a completed nel service:
...
form = new FormGroup({ customerName: new FormControl(''), orderNumber: new FormControl(''), cofeeOrder: new FormControl(''), completed: new FormControl(false), }); ...
L’evento click richiamerà la funzione markCompleted() nel componente.
Ora andiamola a creare nel componete order-list:
... markCompleted = data => this.ordersService.updateCoffeeOrder (data); ...
quindi nel service aggiungi:
…
updateCoffeeOrder(data){ returnthis.firestore.collection ('coffeeOrders') .doc(data.payload.doc.id).set ({ completed:true},{ merge:true}); } ...
Ora nel momento in cui clicchi sull’icona ‘check’ questa aggiornerà il database e sparirà dalla vista in quanto il suo stato sarà passato a hidden.
Eliminare i dati (DELETE)
E per finire andiamo a realizzare il metodo che ci consentirà di eliminare i dati dal database.
Aggiungiamo l’evento click che richiamerà la funzione deleteOrder() all’icona relativa al cestino su order-list html:
...
<td[hidden]="order.payload.doc.data ().completed"(click)="deleteOrder (order)"> <iclass="material-icons"> delete_forever </i> </td> ...
quindi all’interno del relativo componente order-list creiamo la funzione deleteOrder() che a sua volta andrà a richiamare il metodo deleteCoffeeOrder() sul service:
...
deleteOrder = data => this.serviceOrder.deleteCoffeeOrder(data); ...
quindi sul service create la funzione deleteCoffeOrder():
...
/*Metodo delete */ deleteCoffeeOrder(data){ returnthis.firestore.collection ('coffeeOrders') .doc(data.payload.doc.id) .delete(); } ...
Considerazioni finali
In questa guida è stata mia intenzione utilizzare un codice minimale, difatti non è perfetto. Lo scopo principale della stessa era quello di farvi capire come sia facile integrare Firebase con Angular.
Personalmente adoro Firebase per la semplicità con cui è possibile realizzare rapidamente progetti pronti per la messa in produzione. Dal punto di vista dei costi non è male in quanto ti offre la possibilità di effettuare i test gratuiti e , fin quanto non vorrai cambiare piano non sarai costretto ad inserire i dati della tua carta.
Se volete Approfondire le conoscenze su Angular potete seguire il corso completo su Udemy sempre scontato a 9.99/12.99 € , inoltre, nel momento in cui non foste soddisfatti, avete la possibilità di ottenere il rimborso completo dello stesso entro 30 giorni dalla data di acquisto!
Grazie a presto.