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 CLIng
:-
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
.
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.)
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 projects
→ my-memories
→ architect
→ serve
→ configurations
:
"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șierulangular.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șierulindex.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 laAppModule
-
angular.json
avem indigo-tema roz deja inclusă pentru noi
Trebuie să reporniți ng serve
pentru a prelua tema, sau puteți alege o altă temă preinstalată.
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
.
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:
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:
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:
Î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:
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.
Î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:
/src/environments/environment.ts
/src/environments/environment.hmr.ts
/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') }) }
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:
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!
Leave a Reply