Tutoriel Angular 6 : De nouvelles fonctionnalités avec une nouvelle puissance

Angular 6 est sorti ! Les changements les plus remarquables concernent son CLI et la façon dont les services sont injectés. Si vous cherchez à écrire votre toute première application Angular 6 – ou une application Angular/Firebase – dans ce tutoriel, nous passerons en revue les étapes de base de la configuration initiale et créerons une petite application journalière.

Angular 6 : Les bases

Si vous n’avez jamais utilisé Angular auparavant, laissez-moi vous en donner une brève description et vous expliquer comment il fonctionne.

Angular est un framework JavaScript conçu pour prendre en charge la construction d’applications monopages (SPA) pour le bureau et le mobile.

Le framework comprend une suite complète de directives et de modules qui vous permettent de mettre en œuvre facilement certains des scénarios les plus courants pour une application Web, comme la navigation, l’autorisation, les formulaires et les rapports. Il est également livré avec tous les paquets nécessaires pour ajouter des tests à l’aide du framework Jasmine et les exécuter à l’aide des exécuteurs de tests Karma ou Protractor.

L’architecture Angular est basée sur des composants, des modèles, des directives et des services. Il fournit un mécanisme intégré d’injection de dépendances pour vos services, ainsi qu’une liaison de données bidirectionnelle pour connecter vos vues avec votre code de composant.

Angular utilise TypeScript, un surensemble typé de JS, et rendra certaines choses plus faciles, surtout si vous venez d’un contexte de langage typé.

Angular 6 : Nouvelles fonctionnalités

Un bref résumé des nouvelles fonctionnalités d’Angular 6 :

  • Une politique de synchronisation des numéros de version majeurs pour les packages du framework (@angular/core, @angular/common, @angular/compiler, etc.), CLI, Material, et CDK. Cela aidera à rendre la compatibilité croisée plus claire à l’avenir : Vous pouvez dire d’un coup d’œil rapide au numéro de version si les paquets clés sont compatibles entre eux.
  • Nouvelles ng Commandes CLI :
    • ng update pour mettre à niveau les versions des paquets de manière intelligente, en mettant à jour les versions des dépendances et en les gardant synchronisées. (Par exemple, lors de l’exécution de ng update @angular/core, tous les frameworks seront mis à jour ainsi que RxJS.) Il exécutera également les schémas si le paquet les inclut. (Si une version plus récente inclut des changements de rupture qui nécessitent des changements dans le code, le schéma mettra à jour votre code pour vous.)
    • ng add pour ajouter de nouveaux paquets (et exécuter des scripts, le cas échéant)
  • Les services font maintenant référence aux modules qui les fourniront, au lieu que les modules fassent référence aux services, comme c’était le cas auparavant.

A titre d’exemple de ce que signifie ce dernier changement, là où votre code ressemblait auparavant à :

@NgModule({ // ... providers: })

…avec ce changement particulier dans Angular 6, il ressemblera à :

@Injectabe({ providedIn: 'root',})

Ce sont des fournisseurs appelés tree-shakeable et permettent au compilateur de supprimer les services non référencés résultant en des bundles de plus petite taille.

La CLI d’Angular 6

L’interface de ligne de commande ng est une pièce très importante d’Angular et vous permet d’aller plus vite lors du codage de votre application.

Avec la CLI, vous pouvez échafauder votre configuration initiale d’application très facilement, générer de nouveaux composants, des directives, etc, et construire et exécuter votre application dans votre environnement local.

Créer un projet Angular 6

Ok, assez de paroles. Mettons nos mains sales et commençons à coder.

Pour commencer, vous aurez besoin de Node.js et de npm installés sur votre machine.

Maintenant, allons-y et installons le CLI:

npm install -g @angular/cli

Cela installera la commande CLI ng globalement, en raison du commutateur -g.

Une fois que nous avons cela, nous pouvons obtenir l’échafaudage initial pour notre application avec ng new:

ng new my-memories --style=scss

Cela créera un dossier my-memories, créera tous les fichiers nécessaires pour obtenir votre configuration initiale prête à démarrer, et installera tous les paquets nécessaires. Le commutateur --style=scss est facultatif et configurera le compilateur pour compiler les fichiers SCSS en CSS, ce dont nous aurons besoin plus tard.

Une fois l’installation terminée, vous pouvez cd my-memories et exécuter ng serve. Cela lancera le processus de construction et un serveur web local qui sert votre application à http://localhost:4200.

Une application Angular 6 immédiatement après le scaffolding

Ce qui se passe en coulisses, c’est que le CLI transpose tous les .ts (fichiers TypeScript) en vanilla JS, rassemble toutes les dépendances requises à partir du dossier packages node_modules, et sort le résultat dans un ensemble de fichiers qui sont servis via un serveur web local qui fonctionne sur le port 4200.

Fichiers de projet

Si vous n’êtes pas familier avec la structure des dossiers de projet d’Angular, la chose la plus importante que vous devez savoir est que tout le code lié à l’app va à l’intérieur du dossier src. Vous créerez généralement tous vos modules et directives dans ce dossier en suivant l’architecture de votre app (par exemple, utilisateur, panier, produit.)

La structure de dossier du projet Angular 6

Initial Setup

Ok, jusqu’ici nous avons la configuration initiale de notre app. Commençons à faire quelques changements.

Avant de commencer, creusons un peu dans le dossier src. La page initiale est index.html:

<!doctype html><html lang="en"><head> <meta charset="utf-8"> <title>MyMemories</title> <base href="/"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" type="image/x-icon" href="favicon.ico"></head><body> <app-root></app-root></body></html>

Nous voyons ici du HTML de base et la balise <app-root>. C’est un composant Angular, et l’endroit où Angular 6 insère le code de notre composant.

Nous trouverons le fichier app/app.component.ts, qui a le sélecteur app-root pour correspondre à ce qui est dans le fichier index.html.

Le composant est une classe TypeScript décorée, et dans ce cas, contient la propriété title. Le décorateur @Component indique à Angular d’inclure le comportement du composant dans la classe. En plus du sélecteur, il spécifie le fichier HTML à rendre et les feuilles de style à utiliser.

import { Component } from '@angular/core';@Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: })export class AppComponent { title = 'app';}

Si nous regardons app.component.html, nous verrons le binding d’interpolation {{title}}. C’est ici que toute la liaison magique se produit, et Angular rendra la valeur de la propriété du titre de la classe et la mettra à jour chaque fois qu’elle change.

<!--The content below is only a placeholder and can be replaced.--><div style="text-align:center"> <h1> Welcome to {{ title }}! </h1> <img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg=="></div><h2>Here are some links to help you start: </h2><ul> <li> <h2><a target="_blank" rel="noopener" href="https://angular.io/tutorial">Tour of Heroes</a></h2> </li> <li> <h2><a target="_blank" rel="noopener" href="https://github.com/angular/angular-cli/wiki">CLI Documentation</a></h2> </li> <li> <h2><a target="_blank" rel="noopener" href="https://blog.angular.io/">Angular blog</a></h2> </li></ul>

Allons-y et mettons à jour le title de la classe à 'My Memories!'.

...export class AppComponent { title = 'My Memories!';}...

Nous verrons le compilateur traiter notre changement et le navigateur se rafraîchir pour afficher notre titre mis à jour.

Cela signifie que le ng serve d’Angular 6 surveille les changements de notre fichier et effectue un rendu chaque fois qu’un changement est introduit dans un fichier quelconque.

Afin de rendre le codage plus convivial et d’éviter le rafraîchissement complet de la page chaque fois que nous apportons des modifications, nous pouvons profiter de webpack Hot Module Replacement (HMR), qui met juste à jour le morceau de JS/CSS qui a été modifié au lieu de produire un rafraîchissement complet pour montrer vos changements.

Configuration de HMR

D’abord, nous devons configurer l’environnement.

Créer un fichier src/environments/environment.hmr.ts avec le contenu suivant:

export const environment = { production: false, hmr: true};

Mettre à jour src/environments/environment.prod.ts et ajouter le drapeau hmr: false à l’environnement:

export const environment = { production: true, hmr: false};

Puis mettre à jour src/environments/environment.ts et ajouter le drapeau hmr: false à l’environnement là aussi :

export const environment = { production: false, hmr: false};

Puis dans le fichier angular.json, mettez à jour cette partie:

 "projects": { "my-memories": { // ... "architect": { "build": { // ... "configurations": { "hmr":{ "fileReplacements": }, // ...

Et sous projectsmy-memoriesarchitectserveconfigurations :

 "projects": { "my-memories": { "architect": { // ... "serve": { // ... "configurations": { "hmr": { "browserTarget": "my-memories:build:hmr" }, // ...

Mettez maintenant à jour tsconfig.app.json pour inclure le types (enfin, le type) nécessaire en ajoutant ceci sous compilerOptions:

 "compilerOptions": { // ... "types": 

Puis, nous installerons le module @angularclass/hmr comme dépendance de développement:

npm install --save-dev @angularclass/hmr

Puis nous le configurerons en créant un fichier src/hmr.ts :

import { NgModuleRef, ApplicationRef } from '@angular/core';import { createNewHosts } from '@angularclass/hmr';export const hmrBootstrap = (module: any, bootstrap: () => Promise<NgModuleRef<any>>) => { let ngModule: NgModuleRef<any>; module.hot.accept(); bootstrap().then(mod => ngModule = mod); module.hot.dispose(() => { const appRef: ApplicationRef = ngModule.injector.get(ApplicationRef); const elements = appRef.components.map(c => c.location.nativeElement); const makeVisible = createNewHosts(elements); ngModule.destroy(); makeVisible(); });};

Puis, mettez à jour src/main.ts pour utiliser la fonction ci-dessus:

import { enableProdMode } from '@angular/core';import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';import { AppModule } from './app/app.module';import { environment } from './environments/environment';import { hmrBootstrap } from './hmr';if (environment.production) { enableProdMode();}const bootstrap = () => platformBrowserDynamic().bootstrapModule(AppModule);if (environment.hmr) { if (module) { hmrBootstrap(module, bootstrap); } else { console.error('HMR is not enabled for webpack-dev-server!'); console.log('Are you using the --hmr flag for ng serve?'); }} else { bootstrap().catch(err => console.log(err));}

Ce que nous faisons ici est de faire en sorte que bootstrap appelle une fonction anonyme, et ensuite de demander si le drapeau environment.hmr est vrai. Si c’est le cas, nous appelons la fonction précédemment définie de hmr.ts qui a activé le remplacement de module à chaud ; sinon, nous l’amorçons comme nous le faisions auparavant.

Maintenant, lorsque nous exécutons ng serve --hmr --configuration=hmr, nous invoquerons la configuration hmr, et lorsque nous apporterons des modifications aux fichiers, nous obtiendrons des mises à jour sans un rafraîchissement complet. Le premier --hmr est pour webpack, et --configuration=hmr est pour Angular pour utiliser l’environnement hmr.

Progressive Web App (PWA)

Afin d’ajouter le support Angular 6 PWA et d’activer le chargement hors ligne pour l’application, nous pouvons utiliser l’une des nouvelles commandes CLI, ng add:

ng add @angular/

Notez que j’ajoute la version, car la dernière version au moment où j’écrivais ce tutoriel lançait une erreur. (Vous pouvez essayer sans elle et vérifier si elle fonctionne pour vous en utilisant simplement ng add @angular/pwa.)

Ok, donc après avoir exécuté la commande, nous verrons beaucoup de changements sur notre projet. Les changements les plus importants sont qu’il a ajouté :

  • Une référence à manifest.json dans le fichier angular.json assets, afin qu’il soit inclus dans la sortie de la build, ainsi que "serviceWorker": true dans les builds de production
  • Le fichier ngsw-config.json avec la configuration initiale pour mettre en cache tous les fichiers nécessaires au fonctionnement de l’app
  • Une balise méta manifest.json dans le fichier index.html
  • Le fichier manifest.json lui-même, avec une configuration de base pour l’app
  • Le chargement du travailleur de service dans le module app ServiceWorkerModule.register('/ngsw-worker.js', { enabled: environment.production }) (notez que le travailleur de service ne sera activé que dans les environnements de production)

Donc, cela signifie maintenant que lorsque l’utilisateur accède pour la première fois à l’URL, les fichiers seront téléchargés. Après cela, si l’utilisateur essaie d’accéder à l’URL sans service réseau, l’application fonctionnera toujours en tirant ces fichiers mis en cache.

Ajouter la bibliothèque Material Angular 6 UI

Jusqu’ici, nous avons la configuration initiale, et nous sommes prêts à commencer à construire notre application. Pour utiliser des composants déjà construits, nous pouvons utiliser la version Angular 6 de Material.

Afin d’installer le paquet material sur notre app, nous ferons à nouveau usage de ng add:

ng add @angular/material

Après avoir exécuté cela, nous verrons quelques nouveaux paquets ajoutés et une configuration de style de base :

  • index.html inclut la police Roboto et les icônes Material
  • BrowserAnimationsModule est ajouté à notre AppModule
  • angular.json a le thème indigo-thème rose déjà inclus pour nous

Indiquant votre choix d'un thème Angular 6 préconstruit

Vous devrez redémarrer ng serve pour récupérer le thème, ou vous pouvez choisir un autre thème préconstruit.

Relié : Construire des applications Web ultra-modernes avec Angular Material

Mise en page de base

Pour avoir la mise en page initiale du sidenav, nous utiliserons les schémas fournis avec Material. Mais ce n’est pas grave si vous voulez utiliser une disposition différente.

(En bref, les schémas vous permettent d’appliquer des transformations à un projet : Vous pouvez créer, modifier ou supprimer des fichiers selon vos besoins. Dans ce cas, il échafaude une mise en page sidenav pour notre application.)

ng generate @angular/material:material-nav --name=my-nav

Cela créera un composant sidenav avec le minimum de configuration prêt à démarrer. N’est-ce pas génial ?

Il a également inclus tous les modules nécessaires dans notre app.module.ts.

Un composant Angular 6 "my-nav" nouvellement créé

Puisque nous utilisons SCSS, nous devons renommer le fichier my-nav.component.css en my-nav.component.scss, et dans my-nav.component.ts mettre à jour la référence correspondante styleUrls pour utiliser le nouveau nom.

Maintenant pour utiliser le nouveau composant, allons dans app.component.html et supprimons tout le code initial, laissant juste :

<app-my-nav></app-my-nav>

Lorsque nous retournons dans le navigateur, voici ce que nous verrons :

Une mise en page à quatre volets avec Menu dans le coin supérieur gauche, mes souvenirs à côté, et trois liens numérotés sous Menu ; le quatrième volet est vide

Mettons à jour les liens pour avoir juste les deux options que nous voulons.

D’abord, créons deux nouveaux composants :

ng g c AddMemoryng generate @angular/material:material-table --name=view-memories

(Le second est un schéma Matériel utilisé pour créer un tableau.)

Puis, sur my-nav, nous allons mettre à jour pour mettre en place les liens et inclure le <router-outlet> pour afficher nos composants de contenu:

<mat-sidenav-container class="sidenav-container"> <mat-sidenav #drawer class="sidenav" fixedInViewport="true" ="(isHandset$ | async) ? 'dialog' : 'navigation'" ="(isHandset$ | async) ? 'over' : 'side'" ="!(isHandset$ | async)"> <mat-toolbar color="primary">Menu</mat-toolbar> <mat-nav-list> <a mat-list-item ="">Add Memory</a> <a mat-list-item ="">View My Memories</a> </mat-nav-list> </mat-sidenav> <mat-sidenav-content> <mat-toolbar color="primary"> <button type="button" aria-label="Toggle sidenav" mat-icon-button (click)="drawer.toggle()" *ngIf="isHandset$ | async"> <mat-icon aria-label="Side nav toggle icon">menu</mat-icon> </button> <span>my-memories</span> </mat-toolbar> <router-outlet></router-outlet> </mat-sidenav-content></mat-sidenav-container>

Aussi, dans app.component.html, nous devons le mettre à jour pour avoir juste le <router-outlet> principal (c’est-à-dire, supprimer <my-nav>):

<router-outlet></router-outlet>

Puis, sur le AppModule, nous allons inclure les routes:

import { RouterModule, Routes } from '@angular/router';// ...imports: }, ]),]

Notez que nous définissons MyNavComponent comme parent et les deux composants que nous avons créés comme enfants. C’est parce que nous avons inclus le <router-outlet> dans MyNavComponent, et chaque fois que nous touchons l’une de ces deux routes, nous rendrons le composant enfant où le <router-outlet> a été placé.

Après cela, lorsque nous servons l’application, nous devrions voir:

Les liens de gauche ont été remplacés par Ajouter un souvenir et Voir mes souvenirs, avec ce dernier sélectionné. Le volet vide a maintenant un tableau avec des numéros d'id et des noms.

Construire l’application (Un journal de souvenirs)

Ok, maintenant créons le formulaire pour enregistrer de nouveaux souvenirs dans notre journal.

Nous devrons importer quelques modules matériels et le module de formulaires dans notre app.module.ts:

import { FormsModule } from '@angular/forms';import { MatCardModule, MatFormFieldModule, MatInputModule, MatDatepickerModule, MatNativeDateModule } from '@angular/material';// ...Imports:

Et puis dans add-memory.component.html, nous ajouterons le formulaire:

<form #form="ngForm" (ngSubmit)="onSubmit()"> <mat-card class="memory-card"> <mat-card-title> Add a memory </mat-card-title> <mat-card-content> <mat-form-field> <input disabled matInput placeholder="Select the date..." ="memory.date" name="date" ="date"> <mat-datepicker-toggle matSuffix ="date"></mat-datepicker-toggle> <mat-datepicker disabled="false" #date></mat-datepicker> </mat-form-field> <mat-form-field> <textarea placeholder="Enter your memory..." rows="3" maxlength="300" matInput ="memory.text" name="memory"></textarea> </mat-form-field> </mat-card-content> <mat-card-actions> <button mat-button type="submit">Save me!</button> </mat-card-actions> </mat-card></form><pre> {{ memory | json }} </pre>

Ici nous utilisons un mat-card et ajoutons deux champs, un date et un textarea.

Notez que nous utilisons . Cette directive Angular liera l’expression memory.date et la propriété memory de la classe l’une à l’autre, comme nous le verrons plus tard. ( est un sucre syntaxique – un raccourci pour effectuer une liaison de données bidirectionnelle de la classe à la vue et de la vue à la classe. Cela signifie que lorsque vous saisissez du texte dans la vue, memory.date reflétera ces changements dans l’instance de classe, et si vous apportez des changements à memory.date dans l’instance de classe, la vue reflétera ces changements.)

Dans le add-memory.component.ts, le code ressemblera à ceci:

import { Component, OnInit } from '@angular/core';@Component({ selector: 'app-add-memory', templateUrl: './add-memory.component.html', styleUrls: })export class AddMemoryComponent implements OnInit { memory: any = {}; constructor() { } ngOnInit() { } onSubmit() { console.log(this.memory); }}

Ici, nous initialisons la propriété memory liée via ngModel. Lorsque le composant AddMemoryComponent est instancié, memory sera un objet vide. Ensuite, lorsque la directive ngModel s’exécutera, elle pourra affecter la valeur d’entrée à memory.date et memory.text. Si nous ne faisions pas cela, nous aurions une erreur de Cannot set property 'date/text' of undefined.

En attendant, add-memory.component.scss doit avoir :

.memory-card { min-width: 150px; max-width: 400px; width: 100%; margin: auto;}.mat-form-field { width: 100%;}

Puisque nous avons <pre> {{ memory | json }} </pre>, nous pouvons voir l’état actuel de memory dans la vue. Si nous allons dans le navigateur, voici le résultat jusqu’à présent:

Le prototype d

Dans la vue, nous avons lié le formulaire via (ngSubmit)="onSubmit()" à la fonction onSubmit de la classe.

 onSubmit() { console.log(this.memory); }

Ainsi, lorsque vous cliquez sur le bouton « Sauvegardez-moi ! », vous obtenez la représentation interne de l’entrée de l’utilisateur envoyée dans le journal de la console :

La représentation interne de l'entrée de l'utilisateur dans le journal de la console.

Tutoriel Angular 6 : Connexion avec Firebase

Ce que nous allons faire ensuite, c’est connecter notre projet à Firebase afin de sauvegarder nos souvenirs.

D’abord, nous allons aller dans la console Firebase et y créer un projet.

Ajouter un projet Firebase.

Deuxièmement, nous allons installer les paquets firebase et angularfire2:

npm install firebase angularfire2 --save

Et ensuite dans chacun de ces trois fichiers:

  1. /src/environments/environment.ts
  2. /src/environments/environment.hmr.ts
  3. /src/environments/environment.prod.ts

…nous allons ajouter notre config Firebase :

export const environment = {// ... firebase: { apiKey: '<your-key>', authDomain: '<your-project-authdomain>', databaseURL: '<your-database-URL>', projectId: '<your-project-id>', storageBucket: '<your-storage-bucket>', messagingSenderId: '<your-messaging-sender-id>' }};

Vous pouvez obtenir les détails de configuration requis pour les fichiers ci-dessus en cliquant sur « Ajouter Firebase à votre application web » sur la page de présentation du projet.

Après cela, nous inclurons les modules Firebase dans notre app.module.ts:

import { AngularFireModule } from 'angularfire2';import { AngularFireDatabaseModule } from 'angularfire2/database';import { environment } from '../environments/environment';// ...Imports:

Et dans add-memory.component.ts, nous injectons la base de données dans le constructeur et sauvegardons les valeurs du formulaire dans la base de données. Lorsque la promesse de push de Firebase est réussie, nous enregistrons le succès dans la console et réinitialisons le modèle :

import { AngularFireDatabase } from 'angularfire2/database';// ...constructor(private db: AngularFireDatabase) { }// ... onSubmit() { this.memory.date = new Date(this.memory.date).valueOf(); this.db.list('memories').push(this.memory) .then(_ => { this.memory = {} console.log('success') }) }

Autoriser l'accès en lecture et en écriture à votre base de données Firebase.

Vous devrez autoriser l’accès public sur les règles de la base de données, afin que les utilisateurs anonymes puissent lire et écrire dessus. Veuillez noter qu’avec cette configuration, n’importe quel utilisateur serait en mesure de lire/modifier/supprimer vos données. Assurez-vous de configurer vos règles en conséquence avant de passer en production.

De plus, pour récupérer les changements d’environnement, vous devrez redémarrer le processus ng serve.

Maintenant, lorsque nous retournons au navigateur et que nous cliquons sur notre bouton de sauvegarde, nous verrons que la mémoire a été ajoutée à la base de données :

Notre mémoire de test ajoutée à la base de données Firebase de notre application de journal intime.

Regardons comment nous pouvons récupérer nos souvenirs et les afficher dans la table Matériel.

À l’époque, nous avons créé la table en utilisant ng generate @angular/material:material-table --name=view-memories', we automatically got a file view-memories/view-memories-datasource.ts`. Ce fichier contient des données factices, nous devrons donc le modifier pour commencer à tirer de Firebase.

En view-memories-datasource.ts, nous supprimerons le EXAMPLE_DATA et définirons un tableau vide :

export class ViewMemoriesDataSource extends DataSource<ViewMemoriesItem> { data: ViewMemoriesItem = ;// ...

Et en getSortedData, nous mettrons à jour les noms des champs :

private getSortedData(data: ViewMemoriesItem) { if (!this.sort.active || this.sort.direction === '') { return data; } return data.sort((a, b) => { const isAsc = this.sort.direction === 'asc'; switch (this.sort.active) { case 'text': return compare(a.name, b.name, isAsc); case 'date': return compare(+a.id, +b.id, isAsc); default: return 0; } });}

En view-memories.component.html, nous mettrons à jour les noms des colonnes en date et text de notre modèle de mémoire. Notez que puisque nous avons enregistré la date au format millisecondes, nous utilisons ici un pipe de date pour transformer la valeur pour l’affichage dans un format de date plus convivial pour l’homme. Enfin, nous supprimons le ="dataSource.data.length" du paginateur, puisque nous chargerons les données de manière asynchrone depuis Firebase:

<div class="mat-elevation-z8"> <table mat-table #table ="dataSource" matSort aria-label="Elements"> <!-- Id Column --> <ng-container matColumnDef="date"> <th mat-header-cell *matHeaderCellDef mat-sort-header>Date</th> <td mat-cell *matCellDef="let row">{{row.date | date:'short'}}</td> </ng-container> <!-- Name Column --> <ng-container matColumnDef="text"> <th mat-header-cell *matHeaderCellDef mat-sort-header>Text</th> <td mat-cell *matCellDef="let row">{{row.text}}</td> </ng-container> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> </table> <mat-paginator #paginator ="0" ="50" =""> </mat-paginator></div>

Changeons le view-memories.component.css en view-memories.component.scss et définissons le style de la table:

table{ width: 100%;}

Dans view-memories.component.ts, nous changerons le styleUrls pour refléter le renommage ci-dessus en ./view-memories.component.scss. Nous allons également mettre à jour le tableau displayedColumns pour qu’il devienne et configurer la table datasource pour obtenir des données de Firebase.

Ce qui se passe ici, c’est que nous nous abonnons à la liste des mémoires et lorsque nous recevons les données, nous instantions le ViewMemoriesDataSource et définissons sa propriété data avec les données de Firebase.

this.subscription = this.db.list<ViewMemoriesItem>('memories').valueChanges().subscribe(d=>{ console.log('data streaming'); this.dataSource = new ViewMemoriesDataSource(this.paginator, this.sort); this.dataSource.data = d;});

Firebase renvoie un tableau Observable de style ReactiveX.

Notez que nous coulons this.db.list<ViewMemoriesItem>('memories')les valeurs tirées du chemin 'memories'vers ViewMemoriesItem. Ceci est pris en charge par la bibliothèque angularfire2.

Nous avons également inclus l’appel unsubscribe au sein du hook onDestroy du cycle de vie du composant Angular.

import { Component, OnInit, ViewChild, OnDestroy } from '@angular/core';import { MatPaginator, MatSort } from '@angular/material';import { ViewMemoriesDataSource, ViewMemoriesItem } from './view-memories-datasource';import { AngularFireDatabase } from 'angularfire2/database';import { Subscription } from 'rxjs';import { map, first } from 'rxjs/operators';@Component({ selector: 'app-view-memories', templateUrl: './view-memories.component.html', styleUrls: })export class ViewMemoriesComponent implements OnInit, OnDestroy{ @ViewChild(MatPaginator) paginator: MatPaginator; @ViewChild(MatSort) sort: MatSort; dataSource: ViewMemoriesDataSource; /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ; subscription: Subscription; constructor(private db: AngularFireDatabase) { } ngOnInit() { this.subscription = this.db.list<ViewMemoriesItem>('memories').valueChanges().subscribe(d=>{ console.log('data streaming'); this.dataSource = new ViewMemoriesDataSource(this.paginator, this.sort); this.dataSource.data = d; }); } ngOnDestroy(): void { this.subscription.unsubscribe(); }}

Déploiement sur Firebase Hosting

Maintenant, pour faire vivre notre application, déployons-la sur Firebase Hosting. Pour cela, nous allons installer la CLI de Firebase, qui rend la commande firebase disponible :

npm install -g firebase-tools

Maintenant, nous pouvons utiliser la CLI de Firebase pour nous connecter :

firebase login

Ceci vous invitera à sélectionner votre compte Google.

Puis, nous allons initialiser le projet et configurer l’hébergement Firebase:

firebase init

Nous allons juste sélectionner l’option d’hébergement.

Puis, quand on nous demande le chemin d’accès, nous allons le mettre à dist/my-memories. Lorsqu’on nous demandera si nous devons la configurer comme une application à page unique (c’est-à-dire réécrire toutes les URL en /index.html), nous répondrons « oui. »

Enfin, nous frapperons, « Le fichier dist/my-memories/index.html existe déjà. Ecraser ? » Ici, nous dirons « non ».

Ceci va créer les fichiers de configuration Firebase .firebaserc et firebase.json avec la configuration fournie.

La dernière étape consiste à exécuter:

ng build --prodfirebase deploy

Et avec cela, nous aurons publié l’application à la Firebase, qui fournit une URL pour nous de naviguer à, comme https://my-memories-b4c52.firebaseapp.com/view-memories, où vous pouvez voir ma propre démo publiée.

Wow, vous avez parcouru le tutoriel ! J’espère que vous l’avez apprécié. Vous pouvez également consulter le code complet de celui-ci sur GitHub.

Un pas à la fois

Angular est un framework très puissant pour construire des applications web. Il existe depuis longtemps et a fait ses preuves pour les petites apps simples comme pour les grandes apps complexes – Angular 6 ne fait pas exception ici.

À l’avenir, Angular prévoit de continuer à s’améliorer et à suivre les nouveaux paradigmes du web tels que les composants web (Angular Elements). Si vous êtes intéressé par la construction d’applications hybrides, vous pouvez consulter Ionic, qui utilise Angular comme cadre sous-jacent.

Ce tutoriel a couvert des étapes très basiques pour commencer à utiliser Angular, Material et Firebase. Mais vous devez tenir compte du fait que pour les applications du monde réel, vous devrez ajouter la validation, et pour rendre votre application plus facile à maintenir et à mettre à l’échelle, vous voudrez probablement suivre les meilleures pratiques telles que l’utilisation de Services, de composants réutilisables, etc. Cela devra faire l’objet d’un autre article – espérons que celui-ci aura suffi à vous mettre en appétit pour le développement Angular !

Related : Tous les avantages, aucun souci : Un tutoriel Angular 9

Leave a Reply