Angular 6 Tutorial: Caracteristici noi cu putere nouă

Angular 6 a apărut! Cele mai remarcabile schimbări sunt în CLI-ul său și în modul în care serviciile sunt injectate. Dacă doriți să scrieți prima dumneavoastră aplicație Angular 6 – sau o aplicație Angular/Firebase – în acest tutorial, vom trece în revistă pașii de bază ai configurării inițiale și vom crea o mică aplicație de jurnal.

Angular 6: Noțiuni de bază

Dacă nu ați mai folosit Angular până acum, permiteți-mi să vă fac o scurtă descriere a acestuia și a modului în care funcționează.

Angular este un cadru JavaScript conceput pentru a sprijini construirea de aplicații cu o singură pagină (SPA) atât pentru desktop cât și pentru dispozitive mobile.

Cadrul include o suită completă de directive și module care vă permit să implementați cu ușurință unele dintre cele mai comune scenarii pentru o aplicație web, cum ar fi navigarea, autorizarea, formularele și raportarea. De asemenea, vine cu toate pachetele necesare pentru a adăuga teste cu ajutorul cadrului Jasmine și pentru a le rula cu ajutorul rulatorilor de teste Karma sau Protractor.

Arhitectura Angular se bazează pe componente, șabloane, directive și servicii. Oferă un mecanism încorporat de injectare a dependențelor pentru serviciile dvs., precum și o legătură de date bidirecțională pentru a conecta vizualizările dvs. cu codul componentelor.

Angular folosește TypeScript, un superset tipizat al JS, și va face unele lucruri mai ușoare, mai ales dacă veniți dintr-un fundal de limbaj tipizat.

Angular 6: Noile caracteristici

Un scurt rezumat al noilor caracteristici din Angular 6:

  • O politică de sincronizare a numerelor de versiuni majore pentru pachetele cadrului (@angular/core, @angular/common, @angular/compiler, etc.), CLI, Material și CDK. Acest lucru va contribui la o mai mare claritate a compatibilității încrucișate pe viitor: Vă puteți da seama dintr-o privire rapidă la numărul de versiune dacă pachetele cheie sunt compatibile între ele.
  • Noi ng Comenzi CLI ng:
    • ng update pentru a actualiza versiunile pachetelor în mod inteligent, actualizând versiunile dependențelor și menținându-le în sincronizare. (De exemplu, atunci când se execută ng update @angular/core toate framework-urile vor fi actualizate, precum și RxJS.) De asemenea, va rula schemele dacă pachetul le include. (Dacă o versiune mai nouă include modificări de ruptură care necesită modificări în cod, schema va actualiza codul pentru dvs.)
    • ng add pentru a adăuga noi pachete (și a rula scheme, dacă este cazul)
  • Serviciile fac acum referire la modulele care le vor furniza, în loc ca modulele să facă referire la servicii, așa cum era până acum.

Ca un exemplu a ceea ce înseamnă această ultimă schimbare, în cazul în care codul dvs. obișnuia să arate ca:

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

…cu această schimbare particulară în Angular 6, va arăta ca:

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

Acestea se numesc furnizori de tip tree-shakeable și permit compilatorului să elimine serviciile nereferite, rezultând pachete de dimensiuni mai mici.

Angular 6 CLI

Interfața de linie de comandă ng este o piesă foarte importantă a Angular și vă permite să vă mișcați mai repede atunci când vă codificați aplicația.

Cu CLI puteți să vă schematizați foarte ușor configurația inițială a aplicației, să generați noi componente, directive, etc. și să vă construiți și să vă rulați aplicația în mediul local.

Crearea unui proiect Angular 6

Bine, destulă vorbărie. Haideți să ne murdărim mâinile și să începem să codăm.

Pentru a începe, veți avea nevoie de Node.js și npm instalate pe mașina dumneavoastră.

Acum, să mergem mai departe și să instalăm CLI:

npm install -g @angular/cli

Aceasta va instala comanda ng CLI la nivel global, datorită comutatorului -g.

După ce avem asta, putem obține eșafodajul inițial pentru aplicația noastră cu ng new:

ng new my-memories --style=scss

Aceasta va crea un folder my-memories, va crea toate fișierele necesare pentru ca configurația inițială să fie gata de pornire și va instala toate pachetele necesare. Comutatorul --style=scss este opțional și va configura compilatorul pentru a compila fișierele SCSS în CSS, de care vom avea nevoie mai târziu.

După ce instalarea este completă, puteți cd my-memories și rula ng serve. Acest lucru va porni procesul de compilare și un server web local care servește aplicația dvs. la http://localhost:4200.

O aplicație Angular 6 imediat după eșafodaj

Ce se întâmplă în spatele scenei este că CLI transpune toate .ts (fișiere TypeScript) în vanilla JS, adună toate dependențele necesare din dosarul de pachete node_modules și scoate rezultatul într-un set de fișiere care sunt servite prin intermediul unui server web local care rulează pe portul 4200.

File de proiect

Dacă nu sunteți familiarizați cu structura dosarelor de proiect din Angular, cel mai important lucru pe care trebuie să îl știți este că tot codul legat de aplicație se află în interiorul dosarului src. De obicei, veți crea toate modulele și directivele în acel folder urmărind arhitectura aplicației dumneavoastră (de exemplu, utilizator, coș, produs.)

Structura folderului de proiect Angular 6

Configurare inițială

Bine, până acum avem configurarea inițială pentru aplicația noastră. Să începem să facem câteva modificări.

Înainte de a începe, să săpăm puțin în dosarul src. Pagina inițială este 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>

Aici vedem ceva HTML de bază și tag-ul <app-root>. Aceasta este o componentă Angular și unde Angular 6 inserează codul componentei noastre.

Vom găsi fișierul app/app.component.ts, care are selectorul app-root pentru a se potrivi cu ceea ce este în fișierul index.html.

Componenta este o clasă TypeScript decorată și, în acest caz, conține proprietatea title. Decoratorul @Component îi spune lui Angular să includă comportamentul componentei în clasă. În plus față de selector, acesta specifică ce fișier HTML să redea și ce foi de stil să folosească.

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

Dacă ne uităm la app.component.html vom vedea legătura de interpolare {{title}}. Aici se întâmplă toată legătura magică, iar Angular va reda valoarea proprietății de titlu a clasei și o va actualiza de fiecare dată când se schimbă.

<!--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>

Să mergem mai departe și să actualizăm title de la clasă la 'My Memories!'.

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

Vom vedea cum compilatorul procesează modificarea noastră și cum browserul se reîmprospătează pentru a afișa titlul nostru actualizat.

Acest lucru înseamnă că ng serve de la Angular 6 urmărește modificările din fișierul nostru și se redă de fiecare dată când este introdusă o modificare în orice fișier.

Pentru a face codarea mai prietenoasă și pentru a evita reîmprospătarea completă a paginii de fiecare dată când facem modificări, putem profita de webpack Hot Module Replacement (HMR), care actualizează doar bucata de JS/CSS care a fost modificată în loc să producă o reîmprospătare completă pentru a vă arăta modificările.

Configurarea HMR

În primul rând, trebuie să configurăm mediul.

Creăm un fișier src/environments/environment.hmr.ts cu următorul conținut:

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

Actualizați src/environments/environment.prod.ts și adăugați stegulețul hmr: false la mediu:

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

Actualizați apoi src/environments/environment.ts și adăugați și acolo stegulețul hmr: false la mediu:

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

În continuare, în fișierul angular.json, actualizați această parte:

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

Și sub projectsmy-memoriesarchitectserveconfigurations:

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

Acum actualizați tsconfig.app.json pentru a include types necesarul types (bine, tipul) adăugând acest lucru sub compilerOptions:

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

În continuare, vom instala modulul @angularclass/hmr ca dependență de dezvoltare:

npm install --save-dev @angularclass/hmr

Apoi îl vom configura creând un fișier 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(); });};

În continuare, actualizăm src/main.ts pentru a utiliza funcția de mai sus:

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 facem aici este să facem ca bootstrap să apeleze o funcție anonimă, iar apoi să întrebăm dacă stegulețul environment.hmr este adevărat. Dacă este, apelăm funcția definită anterior din hmr.ts care a activat înlocuirea la cald a modulelor; în caz contrar, facem bootstrap așa cum o făceam înainte.

Acum, când executăm ng serve --hmr --configuration=hmr, vom invoca configurația hmr, iar atunci când facem modificări la fișiere, vom primi actualizări fără o reîmprospătare completă. Primul --hmr este pentru webpack, iar --configuration=hmr este pentru ca Angular să folosească mediul hmr.

Progressive Web App (PWA)

Pentru a adăuga suportul Angular 6 PWA și pentru a activa încărcarea offline a aplicației, ne putem folosi de una dintre noile comenzi CLI, ng add:

ng add @angular/

Rețineți că adaug versiunea, deoarece cea mai recentă versiune în momentul în care scriam acest tutorial arunca o eroare. (Puteți încerca fără ea și să verificați dacă funcționează pentru dvs. folosind pur și simplu ng add @angular/pwa.)

Ok, deci după ce am rulat comanda vom vedea o mulțime de schimbări pe proiectul nostru. Cele mai importante modificări sunt că a adăugat:

  • O referință la manifest.json în fișierul angular.json assets, astfel încât să fie inclusă în rezultatul compilării, precum și "serviceWorker": true în compilările de producție
  • Fisierul ngsw-config.json cu configurația inițială pentru a pune în cache toate fișierele necesare pentru ca aplicația să ruleze
  • Un meta tag manifest.json în fișierul index.html
  • Fisierul manifest.json propriu-zis, cu o configurație de bază pentru aplicație
  • Încărcarea lucrătorului de servicii în modulul aplicației ServiceWorkerModule.register('/ngsw-worker.js', { enabled: environment.production }) (rețineți că lucrătorul de servicii va fi activat doar în mediile de producție)

Deci, acest lucru înseamnă acum că atunci când utilizatorul accesează pentru prima dată URL-ul, fișierele vor fi descărcate. După aceea, dacă utilizatorul încearcă să acceseze URL-ul fără serviciul de rețea, aplicația va funcționa în continuare prin extragerea acelor fișiere stocate în memoria cache.

Adaugarea bibliotecii Material Angular 6 UI

Acum avem configurația inițială și suntem gata să începem să construim aplicația noastră. Pentru a utiliza componentele deja construite, putem folosi versiunea Angular 6 a Material.

Pentru a instala pachetul material pe aplicația noastră, ne vom folosi din nou de ng add:

ng add @angular/material

După ce vom rula acest lucru, vom vedea câteva pachete noi adăugate și o configurație de bază a stilului:

    • index.html include fontul Roboto și pictogramele Material
    • BrowserAnimationsModule este adăugat la AppModule
    • angular.json avem indigo-tema roz deja inclusă pentru noi

Indică alegerea dvs. a unei teme Angular 6 prefabricate

Trebuie să reporniți ng serve pentru a prelua tema, sau puteți alege o altă temă preinstalată.

Înrudite: Build Ultra-Modern Web Apps with Angular Material

Basic Layout

Pentru a avea layout-ul sidenav inițial, vom folosi schemele care vin cu Material. Dar este în regulă dacă doriți să folosiți un layout diferit.

(Pe scurt, schemele vă permit să aplicați transformări unui proiect: Puteți crea, modifica sau șterge fișiere după cum este necesar. În acest caz, se schematizează o schemă sidenav pentru aplicația noastră.)

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

Aceasta va crea o componentă sidenav cu configurația minimă, gata de pornire. Nu este grozav?”

Acesta a inclus, de asemenea, toate modulele necesare în app.module.ts.

O componentă Angular 6 "my-nav" nou creată "my-nav"

Din moment ce folosim SCSS, trebuie să redenumim fișierul my-nav.component.css în my-nav.component.scss, iar în my-nav.component.ts să actualizăm referința corespunzătoare styleUrls pentru a folosi noul nume.

Acum, pentru a utiliza noua componentă, să mergem în app.component.html și să eliminăm tot codul inițial, lăsând doar:

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

Când ne întoarcem în browser, iată ce vom vedea:

Un layout cu patru panouri cu Menu în colțul din stânga sus, my-memories lângă el și trei linkuri numerotate sub Menu; al patrulea panou este gol

Să actualizăm linkurile pentru a avea doar cele două opțiuni pe care le dorim.

În primul rând, să creăm două componente noi:

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

(Cea de-a doua este o schemă de Material folosită pentru a crea un tabel.)

În continuare, în my-nav vom actualiza pentru a configura legăturile și vom include <router-outlet> pentru a afișa componentele noastre de conținut:

<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>

De asemenea, în app.component.html trebuie să o actualizăm pentru a avea doar <router-outlet> principal (adică, eliminați <my-nav>):

<router-outlet></router-outlet>

În continuare, pe AppModule vom include rutele:

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

Rețineți că setăm MyNavComponent ca părinte și cele două componente pe care le-am creat ca și copii. Acest lucru se datorează faptului că am inclus <router-outlet> în MyNavComponent și, ori de câte ori vom accesa una dintre aceste două rute, vom reda componenta copil în care a fost plasată <router-outlet>.

După aceasta, când vom servi aplicația ar trebui să vedem:

Legăturile din stânga au fost înlocuite cu Add Memory și View My Memories, cu cea din urmă selectată. Panoul gol are acum un tabel cu numere de identificare și nume.

Constituirea aplicației (Un jurnal de amintiri)

Bine, acum să creăm formularul pentru a salva noi amintiri în jurnalul nostru.

Vom avea nevoie să importăm câteva module materiale și modulul de formulare în app.module.ts:

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

Și apoi, în add-memory.component.html, vom adăuga formularul:

<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>

Aici folosim un mat-card și adăugăm două câmpuri, un date și un textarea.

Rețineți că folosim . Această directivă Angular va lega expresia memory.date și proprietatea memory din clasă una de cealaltă, după cum vom vedea mai târziu. ( este un zahăr sintactic – o prescurtare pentru a efectua o legătură de date bidirecțională de la clasă la vizualizare și de la vizualizare la clasă. Aceasta înseamnă că atunci când introduceți text în vizualizare, memory.date va reflecta aceste modificări în instanța clasei, iar dacă faceți modificări la memory.date în instanța clasei, vizualizarea va reflecta modificările.)

În add-memory.component.ts, codul va arăta astfel:

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); }}

Aici inițializăm proprietatea memory legată prin ngModel. La instanțierea componentei AddMemoryComponent, memory va fi un obiect gol. Apoi, când se execută directiva ngModel, aceasta va putea să atribuie valoarea de intrare la memory.date și memory.text. Dacă nu am face acest lucru, am obține o eroare de Cannot set property 'date/text' of undefined.

Între timp, add-memory.component.scss trebuie să aibă:

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

Din moment ce avem <pre> {{ memory | json }} </pre>, putem vedea starea actuală a lui memory în vizualizare. Dacă mergem în browser, iată rezultatul de până acum:

Prototipul aplicației de jurnal "my-memories", care arată reprezentarea internă a datelor introduse de utilizator (dată și text.)

În vizualizare, am legat formularul prin (ngSubmit)="onSubmit()" la funcția onSubmit din clasă.

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

Atunci când faceți clic pe butonul „Save me!”, veți obține reprezentarea internă a intrării utilizatorului trimisă în jurnalul consolei:

Reprezentarea internă a intrării utilizatorului în jurnalul consolei.

Angular 6 Tutorial: Conectarea cu Firebase

Ce vom face în continuare este să conectăm proiectul nostru la Firebase pentru a ne salva memoriile.

În primul rând, vom merge la consola Firebase și vom crea un proiect acolo.

Aducerea unui proiect Firebase.

În al doilea rând, vom instala pachetele firebase și angularfire2:

npm install firebase angularfire2 --save

Și apoi, în fiecare dintre aceste trei fișiere:

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

… vom adăuga configurația noastră 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>' }};

Puteți obține detaliile de configurare necesare pentru fișierele de mai sus făcând clic pe „Add Firebase to your web app” (Adăugați Firebase la aplicația dvs. web) pe pagina de prezentare a proiectului.

După aceea, vom include modulele Firebase în app.module.ts:

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

Și în add-memory.component.ts, vom injecta baza de date în constructor și vom salva valorile din formular în baza de date. Atunci când promisiunea push de la Firebase are succes, înregistrăm succesul în consolă și resetăm modelul:

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') }) }

Permiterea accesului de citire și scriere la baza de date Firebase.

Trebuie să permiteți accesul public la regulile bazei de date, astfel încât utilizatorii anonimi să poată citi și scrie în ea. Rețineți că, cu această configurație, orice utilizator ar putea citi/modifica/șterge datele aplicației dvs. Asigurați-vă că vă configurați regulile în mod corespunzător înainte de a trece la producție.

De asemenea, pentru a prelua modificările de mediu, va trebui să reporniți procesul ng serve.

Acum, când ne întoarcem în browser și facem clic pe butonul de salvare, vom vedea că memoria a fost adăugată la baza de date:

Memoria noastră de test adăugată la baza de date Firebase a aplicației noastre de jurnal.

Să aruncăm o privire la modul în care putem prelua amintirile noastre și să le afișăm în tabelul Material.

Înapoi când am creat tabelul folosind ng generate @angular/material:material-table --name=view-memories', we automatically got a file view-memories/view-memories-datasource.ts`. Acest fișier conține date false, așa că va trebui să-l modificăm pentru a începe să tragem de la Firebase.

În view-memories-datasource.ts, vom elimina EXAMPLE_DATA și vom seta o matrice goală:

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

Și în getSortedData vom actualiza numele câmpurilor:

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; } });}

În view-memories.component.html vom actualiza numele coloanelor în date și text din modelul nostru de memorie. Rețineți că, din moment ce am salvat data în format milisecunde, aici folosim o conductă de date pentru a transforma valoarea pentru afișare într-un format de dată mai ușor de utilizat de către oameni. În cele din urmă, eliminăm ="dataSource.data.length" din paginator, deoarece vom încărca datele în mod asincron din 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>

Schimbăm view-memories.component.css în view-memories.component.scss și setăm stilul tabelului:

table{ width: 100%;}

În view-memories.component.ts, vom schimba styleUrls pentru a reflecta redenumirea de mai sus în ./view-memories.component.scss. De asemenea, vom actualiza matricea displayedColumns pentru a fi și vom configura sursa de date a tabelului pentru a obține date de la Firebase.

Ce se întâmplă aici este că ne abonăm la lista de memorii și când primim datele instanțiem ViewMemoriesDataSource și setăm proprietatea sa de date cu datele de la 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 returnează o matrice Observable în stil ReactiveX.

Rețineți că distribuim this.db.list<ViewMemoriesItem>('memories') – valorile extrase din calea 'memories' – în ViewMemoriesItem. De acest lucru se ocupă biblioteca angularfire2.

Am inclus, de asemenea, apelul unsubscribe în cadrul cârligului onDestroy din ciclul de viață al componentei 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(); }}

Deploying to Firebase Hosting

Acum, pentru a face aplicația noastră live, haideți să o desfășurăm la Firebase Hosting. Pentru aceasta, vom instala Firebase CLI, care face disponibilă comanda firebase:

npm install -g firebase-tools

Acum putem folosi Firebase CLI pentru a ne loga:

firebase login

Aceasta vă va cere să selectați contul Google.

În continuare, vom inițializa proiectul și vom configura Firebase Hosting:

firebase init

Vom selecta doar opțiunea Hosting.

În continuare, când ni se cere calea, o vom seta la dist/my-memories. Când vom fi întrebați dacă dorim să o configurăm ca o aplicație cu o singură pagină (adică să rescriem toate URL-urile la /index.html), vom răspunde „da.”

În cele din urmă, vom lovi: „File dist/my-my-memories/index.html already exists. Suprascrieți?” Aici vom răspunde „nu”.”

Aceasta va crea fișierele de configurare Firebase .firebaserc și firebase.json cu configurația furnizată.

Ultimul pas este să rulați:

ng build --prodfirebase deploy

Și cu asta, vom fi publicat aplicația în Firebase, care ne oferă un URL la care putem naviga, cum ar fi https://my-memories-b4c52.firebaseapp.com/view-memories, unde puteți vedea propriul meu demo publicat.

Wow, ați trecut prin tutorial! Sper că v-a plăcut. Puteți, de asemenea, să consultați codul complet al acestuia pe GitHub.

Un pas la un moment dat

Angular este un framework foarte puternic pentru construirea de aplicații web. Există de mult timp și s-a dovedit atât pentru aplicațiile mici și simple, cât și pentru cele mari și complexe – Angular 6 nu face excepție în acest caz.

În viitor, Angular intenționează să continue să se îmbunătățească și să urmeze noile paradigme web, cum ar fi componentele web (Angular Elements). Dacă sunteți interesat să construiți aplicații hibride, puteți verifica Ionic, care utilizează Angular ca și cadru de bază.

Acest tutorial a acoperit pașii foarte de bază pentru a începe să utilizați Angular, Material și Firebase. Dar ar trebui să țineți cont de faptul că, pentru aplicațiile din lumea reală, va trebui să adăugați validare și, pentru ca aplicația dvs. să fie mai ușor de întreținut și de scalat, probabil că veți dori să urmați cele mai bune practici, cum ar fi utilizarea Serviciilor, a componentelor reutilizabile etc. Acesta va trebui să fie subiectul unui alt articol – să sperăm că acesta a fost suficient pentru a vă deschide apetitul pentru dezvoltarea Angular!

Legate: All Perks, No Hassle: Un tutorial Angular 9

Leave a Reply