Tutoriel Angular 6 : Nouvelles fonctionnalités avec une nouvelle puissance
Publié: 2022-03-11Angular 6 est sorti ! Les changements les plus remarquables concernent sa CLI et la manière dont les services sont injectés. Si vous cherchez à écrire votre toute première application Angular 6 - ou application Angular / Firebase - dans ce didacticiel, nous passerons en revue les étapes de base de la configuration initiale et créerons une petite application de journal.
Angulaire 6 : Les bases
Si vous n'avez jamais utilisé Angular auparavant, laissez-moi vous en donner une brève description et comment cela fonctionne.
Angular est un framework JavaScript conçu pour prendre en charge la création d'applications monopage (SPA) pour les ordinateurs de bureau et mobiles.
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, tels que la navigation, l'autorisation, les formulaires et la création de rapports. Il est également livré avec tous les packages nécessaires pour ajouter des tests à l'aide du framework Jasmine et les exécuter à l'aide des testeurs Karma ou Protractor.
L'architecture angulaire est basée sur des composants, des modèles, des directives et des services. Il fournit un mécanisme d'injection de dépendances intégré pour vos services, ainsi qu'une liaison de données bidirectionnelle pour connecter vos vues à votre code de composant.
Angular utilise TypeScript, un sur-ensemble typé de JS, et facilitera certaines choses, surtout si vous venez d'un environnement de langage typé.
Angulaire 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 de framework (
@angular/core
,@angular/common
,@angular/compiler
, etc.), CLI, Material et CDK. Cela contribuera à clarifier la compatibilité croisée à l'avenir : vous pouvez savoir d'un simple coup d'œil au numéro de version si les packages de clés sont compatibles les uns avec les autres. - Nouvelles commandes CLI
ng
:-
ng update
pour mettre à jour intelligemment les versions des packages, en mettant à jour les versions des dépendances et en les maintenant synchronisées. (Par exemple, lors de l'exécution deng update @angular/core
tous les frameworks seront mis à jour ainsi que RxJS.) Il exécutera également des schémas si le package les inclut. (Si une version plus récente inclut des modifications avec rupture qui nécessitent des modifications du code, le schéma mettra à jour votre code pour vous.) -
ng add
pour ajouter de nouveaux packages (et exécuter des scripts, le cas échéant)
-
- Les services référencent désormais les modules qui les fourniront, au lieu des modules référençant les services, comme ils le faisaient auparavant.
À titre d'exemple de ce que signifie ce dernier changement, où votre code ressemblait à :
@NgModule({ // ... providers: [MyService] })
… avec ce changement particulier dans Angular 6, cela ressemblera à :
@Injectabe({ providedIn: 'root', })
Ceux-ci sont appelés fournisseurs arborescents et permettent au compilateur de supprimer les services non référencés, ce qui donne des ensembles de plus petite taille.
CLI angulaire 6
L'interface de ligne de commande ng
est un élément très important d'Angular et vous permet d'avancer plus rapidement lors du codage de votre application.
Avec la CLI, vous pouvez échafauder très facilement la configuration initiale de votre application, générer de nouveaux composants, directives, etc., et créer et exécuter votre application dans votre environnement local.
Création d'un projet angulaire 6
Bon, assez parlé. Mettons nos mains dans le cambouis et commençons à coder.
Pour commencer, vous aurez besoin de Node.js et npm installés sur votre machine.
Maintenant, allons-y et installons la 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 préparer votre configuration initiale et installera tous les packages nécessaires. Le --style=scss
est facultatif et configurera le compilateur pour compiler les fichiers SCSS en CSS, 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 servira votre application à http://localhost:4200
.
Ce qui se passe dans les coulisses, c'est que la CLI transpile tous les .ts
(fichiers TypeScript) en vanilla JS, rassemble toutes les dépendances requises à partir du dossier de packages node_modules
et affiche 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'application va dans le dossier src
. Vous créerez généralement tous vos modules et directives dans ce dossier en suivant l'architecture de votre application (par exemple, utilisateur, panier, produit).
La configuration initiale
Bon, jusqu'à présent, nous avons la configuration initiale de notre application. Commençons à faire quelques changements.
Avant de commencer, fouillons 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>
Ici, nous voyons du HTML de base et la <app-root>
. Il s'agit d'un composant angulaire, et où Angular 6 insère notre code de composant.
Nous trouverons le fichier app/app.component.ts
, qui a le sélecteur app-root
pour correspondre à ce qui se trouve 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 à afficher et les feuilles de style à utiliser.
import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent { title = 'app'; }
Si nous regardons app.component.html
nous verrons la liaison d'interpolation {{title}}
. C'est là que se produit toute la liaison magique, et Angular restituera la valeur de la propriété title de la classe et la mettra à jour à chaque fois qu'elle changera.
<!--The content below is only a placeholder and can be replaced.--> <div> <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 en 'My Memories!'
.
... export class AppComponent { title = 'My Memories!'; } ...
Nous verrons le compilateur traiter notre modification et l'actualisation du navigateur pour afficher notre titre mis à jour.
Cela signifie que ng serve
d'Angular 6 surveille les modifications de nos fichiers et s'affiche chaque fois qu'une modification est introduite dans un fichier.
Afin de rendre le codage plus convivial et d'éviter l'actualisation complète de la page à chaque fois que nous apportons des modifications, nous pouvons tirer parti du Webpack Hot Module Replacement (HMR), qui met simplement à jour le morceau de JS/CSS qui a été modifié au lieu de produire une actualisation complète pour affichez vos modifications.
Configuration de l'HMR
Tout d'abord, nous devons configurer l'environnement.
Créez un fichier src/environments/environment.hmr.ts
avec le contenu suivant :
export const environment = { production: false, hmr: true };
Mettez à jour src/environments/environment.prod.ts
et ajoutez le drapeau hmr: false
à l'environnement :
export const environment = { production: true, hmr: false };
Ensuite, mettez à jour src/environments/environment.ts
et ajoutez également le drapeau hmr: false
à l'environnement :
export const environment = { production: false, hmr: false };
Ensuite, dans le fichier angular.json
, mettez à jour cette partie :
"projects": { "my-memories": { // ... "architect": { "build": { // ... "configurations": { "hmr":{ "fileReplacements":[ { "replace": "src/environments/environment.ts", "with": "src/environments/environment.hmr.ts" } ] }, // ...
Et sous projects
→ my-memories
→ architect
→ serve
→ configurations
:
"projects": { "my-memories": { "architect": { // ... "serve": { // ... "configurations": { "hmr": { "browserTarget": "my-memories:build:hmr" }, // ...
Maintenant, mettez à jour tsconfig.app.json
pour inclure les types
nécessaires (enfin, type) en ajoutant ceci sous compilerOptions
:
"compilerOptions": { // ... "types": [ "node" ]
Ensuite, nous allons installer le @angularclass/hmr
en tant que dépendance de développement :
npm install --save-dev @angularclass/hmr
Configurez-le ensuite 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(); }); };
Ensuite, 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[ 'hot' ]) { 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, c'est faire en sorte que bootstrap appelle une fonction anonyme, puis 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 permis le remplacement de module à chaud ; sinon, nous l'amorçons comme avant.
Maintenant, lorsque nous exécuterons ng serve --hmr --configuration=hmr
, nous appellerons la configuration hmr
, et lorsque nous apporterons des modifications aux fichiers, nous obtiendrons des mises à jour sans actualisation complète. Le premier --hmr
est pour webpack, et --configuration=hmr
est pour Angular d'utiliser l'environnement hmr
.
Application Web progressive (PWA)
Afin d'ajouter la prise en charge d'Angular 6 PWA et d'activer le chargement hors ligne de l'application, nous pouvons utiliser l'une des nouvelles commandes CLI, ng add
:
ng add @angular/[email protected]
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 et vérifier si cela fonctionne pour vous en utilisant simplement ng add @angular/pwa
.)
D'accord, 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 de ressourcesangular.json
, afin qu'il soit inclus dans la sortie de la génération, ainsi que"serviceWorker": true
dans les générations de production - Le fichier
ngsw-config.json
avec la configuration initiale pour mettre en cache tous les fichiers nécessaires à l'exécution de l'application - Une balise meta
manifest.json
dans le fichierindex.html
- Le fichier
manifest.json
lui-même, avec une configuration de base pour l'application - Le service worker charge dans le module d'application
ServiceWorkerModule.register('/ngsw-worker.js', { enabled: environment.production })
(notez que le service worker ne sera activé que dans les environnements de production)
Ainsi, 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 extrayant ces fichiers mis en cache.
Ajout de la bibliothèque d'interface utilisateur Material Angular 6
Jusqu'à présent, nous avons la configuration initiale et nous sommes prêts à commencer à créer notre application. Pour utiliser des composants déjà construits, nous pouvons utiliser la version Angular 6 de Material.
Afin d'installer le package material
sur notre application, nous utiliserons à nouveau ng add
:
ng add @angular/material
Après avoir exécuté cela, nous verrons de nouveaux packages ajoutés et une configuration de style de base :
-
index.html
inclut la police Roboto et les icônes Material -
BrowserAnimationsModule
est ajouté à notreAppModule
-
angular.json
a le thème indigo-pink déjà inclus pour nous
Vous devrez redémarrer ng serve
pour récupérer le thème, ou vous pouvez choisir un autre thème prédéfini.
Disposition de base
Pour avoir la disposition initiale du sidenav, nous utiliserons les schémas fournis avec Material. Mais ce n'est pas grave si vous souhaitez utiliser une mise en page différente.
(En un mot, 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 la configuration minimale prête à démarrer. N'est-ce pas génial ?
Il a également inclus tous les modules nécessaires dans notre app.module.ts
.
Puisque nous utilisons SCSS, nous devons renommer le fichier my- my-nav.component.css
en my-nav.component.scss
, et dans my-nav.component.ts
mettre à jour les styleUrls
de référence correspondants pour utiliser le nouveau nom.
Maintenant, pour utiliser le nouveau composant, allons sur app.component.html
et supprimons tout le code initial, en laissant juste :
<app-my-nav></app-my-nav>
Lorsque nous revenons au navigateur, voici ce que nous verrons :
Mettons à jour les liens pour n'avoir que les deux options que nous voulons.
Commençons par créer deux nouveaux composants :
ng gc AddMemory ng generate @angular/material:material-table --name=view-memories
(Le second est un schéma de matériau utilisé pour créer une table.)
Ensuite, sur my-nav
nous mettrons à jour pour configurer 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" [attr.role]="(isHandset$ | async) ? 'dialog' : 'navigation'" [mode]="(isHandset$ | async) ? 'over' : 'side'" [opened]="!(isHandset$ | async)"> <mat-toolbar color="primary">Menu</mat-toolbar> <mat-nav-list> <a mat-list-item [routerLink]="['/add-memory']">Add Memory</a> <a mat-list-item [routerLink]="['/view-memories']">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>
De plus, dans app.component.html
, nous devons le mettre à jour pour n'avoir que le principal <router-outlet>
(c'est-à-dire supprimer <my-nav>
):
<router-outlet></router-outlet>
Ensuite, sur l' AppModule
, nous inclurons les routes :
import { RouterModule, Routes } from '@angular/router'; // ... imports: [ // ... RouterModule.forRoot([ { path: '', component: MyNavComponent, children: [ { path: 'add-memory', component: AddMemoryComponent }, { path: 'view-memories', component: ViewMemoriesComponent } ] }, ]), ]
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 atteignons l'un de ces deux itinéraires, nous rendrons le composant enfant où le <router-outlet>
a été placé.
Après cela, lorsque nous servons l'application, nous devrions voir :
Construire l'application (un journal de souvenirs)
Bon, créons maintenant le formulaire pour enregistrer de nouveaux souvenirs dans notre journal.
Nous devrons importer certains modules de matériaux 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:[ // ... MatCardModule, MatFormFieldModule, MatInputModule, MatDatepickerModule, FormsModule, MatNativeDateModule, // ... ]
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..." [(ngModel)]="memory.date" name="date" [matDatepicker]="date"> <mat-datepicker-toggle matSuffix [for]="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 [(ngModel)]="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, une date
et un textarea
.
Notez que nous utilisons [(ngModel)]
. Cette directive angulaire liera l'expression memory.date
et la propriété memory
de la classe, comme nous le verrons plus tard. ( [(ngModel)]
est du 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 modifications dans l'instance de classe, et si vous apportez des modifications à memory.date
dans l'instance de classe, la vue reflétera les modifications.)
Dans 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: ['./add-memory.component.scss'] }) 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 le faisions pas, nous aurions une erreur Cannot set property 'date/text' of undefined
.
Pendant ce temps, 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>
<pre> {{ memory | json }} </pre>
nous pouvons voir l'état actuel de la memory
dans la vue. Si nous allons dans le navigateur, voici le résultat jusqu'à présent :
Dans la vue, nous avons lié le formulaire via (ngSubmit)="onSubmit()"
à la fonction onSubmit
dans la classe.
onSubmit() { console.log(this.memory); }
Ainsi, lorsque vous cliquez sur "Sauvez-moi!" , vous obtiendrez la représentation interne de l'entrée utilisateur envoyée au journal de la console :
Tutoriel Angular 6 : Connexion avec Firebase
Nous allons ensuite connecter notre projet à Firebase afin de sauvegarder nos souvenirs.
Tout d'abord, nous allons accéder à la console Firebase et y créer un projet.
Deuxièmement, nous allons installer les firebase
et angularfire2
:
npm install firebase angularfire2 --save
Et puis dans chacun de ces trois fichiers :
-
/src/environments/environment.ts
-
/src/environments/environment.hmr.ts
-
/src/environments/environment.prod.ts
… nous ajouterons notre configuration 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:[ // ... AngularFireModule.initializeApp(environment.firebase), AngularFireDatabaseModule, // ... ]
Et dans add-memory.component.ts
, nous injectons la base de données dans le constructeur et enregistrons les valeurs du formulaire dans la base de données. Lorsque la promesse push de Firebase réussit, 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') }) }
Vous devrez autoriser l'accès public aux règles de la base de données, afin que les utilisateurs anonymes puissent y lire et y écrire. Veuillez noter qu'avec cette configuration, n'importe quel utilisateur pourra lire/modifier/supprimer les données de votre application. Assurez-vous de configurer vos règles en conséquence avant de passer en production.
De plus, pour prendre en compte les modifications de l'environnement, vous devrez redémarrer le processus de ng serve
.
Maintenant, lorsque nous revenons au navigateur et que nous cliquons sur notre bouton Enregistrer, nous verrons que la mémoire a été ajoutée à la base de données :
Voyons comment nous pouvons récupérer nos souvenirs et les afficher dans la table Material.
Lorsque nous avons créé la table à l'aide de ng generate @angular/material:material-table --name=view-memories', we automatically got a file
view-memories/view-memories-datasource.ts`. Ce fichier contient de fausses données, nous devrons donc le modifier pour commencer à extraire de Firebase.
Dans view-memories-datasource.ts
, nous supprimerons EXAMPLE_DATA
et définirons un tableau vide :
export class ViewMemoriesDataSource extends DataSource<ViewMemoriesItem> { data: ViewMemoriesItem[] = []; // ...
Et dans 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; } }); }
Dans view-memories.component.html
nous mettrons à jour les noms des colonnes à date
et le text
de notre modèle de mémoire. Notez que puisque nous avons enregistré la date au format millisecondes, nous utilisons ici un tube de date pour transformer la valeur à afficher dans un format de date plus convivial. Enfin, nous supprimons le [length]="dataSource.data.length"
du paginateur, car nous chargerons les données de manière asynchrone depuis Firebase :
<div class="mat-elevation-z8"> <table mat-table #table [dataSource]="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 [pageIndex]="0" [pageSize]="50" [pageSizeOptions]="[25, 50, 100, 250]"> </mat-paginator> </div>
Remplacez view-memories.component.css
par view-memories.component.scss
et définissez le style de tableau :
table{ width: 100%; }
Dans view-memories.component.ts
, nous allons modifier les styleUrls
pour refléter le changement de nom ci-dessus en ./view-memories.component.scss
. Nous allons également mettre à jour le tableau displayedColumns
pour qu'il soit ['date', 'text']
et configurer la source de données de la table pour obtenir les 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 instancions 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 transtypons this.db.list<ViewMemoriesItem>('memories')
—les valeurs extraites du chemin 'memories'
—en ViewMemoriesItem
. Ceci est pris en charge par la bibliothèque angularfire2
.
Nous avons également inclus l'appel de unsubscribe
dans le 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: ['./view-memories.component.scss'] }) 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 = ['date', 'text']; 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 l'hébergement Firebase
Maintenant, pour rendre notre application active, déployons-la sur Firebase Hosting. Pour cela, nous allons installer la CLI Firebase, qui rend disponible la commande firebase
:
npm install -g firebase-tools
Nous pouvons maintenant utiliser Firebase CLI pour nous connecter :
firebase login
Cela vous demandera de sélectionner votre compte Google.
Ensuite, nous allons initialiser le projet et configurer Firebase Hosting :
firebase init
Nous allons simplement sélectionner l'option Hébergement.
Ensuite, lorsqu'on nous demandera le chemin, nous le définirons sur dist/my-memories
. Lorsqu'on nous demande si nous devons le configurer en tant qu'application d'une seule page (c'est-à-dire réécrire toutes les URL dans /index.html
), nous répondons « oui ».
Enfin, nous allons frapper, "Le fichier dist/my-memories/index.html existe déjà. Écraser?" Ici, nous dirons "non".
Cela créera les fichiers de configuration Firebase .firebaserc
et firebase.json
avec la configuration fournie.
La dernière étape consiste à exécuter :
ng build --prod firebase deploy
Et avec cela, nous aurons publié l'application sur Firebase, qui nous fournit une URL vers laquelle naviguer, comme https://my-memories-b4c52.firebaseapp.com/view-memories, où vous pouvez voir mes propres publications démo.
Wow, vous avez suivi le tutoriel ! J'espère que vous avez aimé. Vous pouvez également consulter le code complet correspondant sur GitHub.
Un pas après l'autre
Angular est un framework très puissant pour créer des applications Web. Il existe depuis longtemps et a fait ses preuves pour les petites applications simples et les grandes applications complexes - Angular 6 ne fait pas exception ici.
À l'avenir, Angular prévoit de continuer à améliorer et à suivre les nouveaux paradigmes Web tels que les composants Web (éléments angulaires). Si vous êtes intéressé par la création 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 une validation, et pour faciliter la maintenance et l'évolution de votre application, 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-le, celui-ci a suffi à vous ouvrir l'appétit pour le développement angulaire !