Angular 6 Tutorial: Új funkciók új erővel

Angular 6 megjelent! A legkiemelkedőbb változások a CLI-jét és a szolgáltatások injektálásának módját érintik. Ha a legelső Angular 6-os alkalmazásodat – vagy Angular/Firebase alkalmazást – szeretnéd megírni, ebben a bemutatóban átvesszük a kezdeti beállítások alapvető lépéseit, és létrehozunk egy kis naplóalkalmazást.

Angular 6: Az alapok

Ha még sosem használtad az Angular-t, hadd adjak egy rövid leírást róla és a működéséről.

Angular egy JavaScript-keretrendszer, amelyet az egyoldalas alkalmazások (SPA-k) építésének támogatására terveztek asztali és mobileszközökre egyaránt.

A keretrendszer irányelvek és modulok teljes készletét tartalmazza, amelyek segítségével könnyedén megvalósíthatja a webes alkalmazások leggyakoribb forgatókönyveit, például a navigációt, az engedélyezést, az űrlapokat és a jelentéstételt. Emellett tartalmazza az összes szükséges csomagot a Jasmine keretrendszerrel történő tesztek hozzáadásához és azok futtatásához a Karma vagy Protractor tesztfuttatókkal.

Angular architektúra a komponensekre, sablonokra, direktívákra és szolgáltatásokra épül. Beépített függőségi injektálási mechanizmust biztosít a szolgáltatások számára, valamint kétirányú adatkötést a nézetek és a komponenskód összekapcsolására.

Angular TypeScriptet használ, ami a JS egy tipizált szuperhalmaza, és megkönnyít néhány dolgot, különösen, ha tipizált nyelvi háttérrel rendelkezel.

Angular 6: Új funkciók

Az Angular 6 újdonságainak rövid összefoglalása:

  • A keretrendszercsomagok (@angular/core, @angular/common, @angular/compiler stb.), a CLI, a Material és a CDK fő verziószámainak szinkronizálásának irányelve. Ez segíteni fogja a keresztkompatibilitás egyértelműbbé tételét a jövőben: A verziószámra vetett gyors pillantásból meg lehet állapítani, hogy a kulcscsomagok kompatibilisek-e egymással.
  • Új ng CLI-parancsok:
    • ng update a csomagverziók okos frissítéséhez, a függőségi verziók frissítéséhez és szinkronban tartásához. (Pl. a ng update @angular/core futtatásakor az összes keretrendszer és az RxJS is frissül.) A program lefuttatja a sémákat is, ha a csomag tartalmazza azokat. (Ha egy újabb verzió olyan törést okozó változásokat tartalmaz, amelyek kódmódosítást igényelnek, a séma frissíti helyetted a kódodat.)
    • ng add új csomagok hozzáadásához (és adott esetben szkriptek futtatásához)
  • A szolgáltatások most már az őket biztosító modulokra hivatkoznak, nem pedig a modulok hivatkoznak a szolgáltatásokra, ahogy eddig volt.

Egy példa arra, hogy mit jelent ez utóbbi változás, ahol a kódod korábban így nézett ki:

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

…ezzel a bizonyos változással az Angular 6-ban így fog kinézni:

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

Ezeket nevezzük tree-shakeable providereknek, és lehetővé teszik a fordító számára, hogy eltávolítsa a nem hivatkozott szolgáltatásokat, ami kisebb méretű csomagokat eredményez.

Angular 6 CLI

A ng parancssori felület egy nagyon fontos része az Angularnak, és lehetővé teszi, hogy gyorsabban haladj az alkalmazásod kódolása során.

A CLI segítségével nagyon könnyen felépítheted az alkalmazás kezdeti beállításait, új komponenseket, direktívákat stb. generálhatsz, és építheted és futtathatod az alkalmazásodat a helyi környezetedben.

Egy Angular 6 projekt létrehozása

Oké, elég a beszédből. Koszoljuk be a kezünket, és kezdjünk el kódolni.

Kezdéshez szükségünk lesz a Node.js és az npm telepítésére a gépünkön.

Most, menjünk előre és telepítsük a CLI-t:

npm install -g @angular/cli

Ez a ng CLI parancsot fogja globálisan telepíteni, a -g kapcsolónak köszönhetően.

Ha ez megvan, akkor a ng new segítségével megkapjuk az alkalmazásunk kezdeti állványzatát:

ng new my-memories --style=scss

Ez létrehoz egy my-memories mappát, létrehozza az összes szükséges fájlt, hogy a kezdeti beállítás készen álljon az indításra, és telepíti az összes szükséges csomagot. A --style=scss kapcsoló opcionális, és beállítja a fordítót, hogy az SCSS fájlokat CSS-re fordítsa, amire később szükségünk lesz.

Amikor a telepítés befejeződött, akkor cd my-memories és futtathatjuk a ng serve. Ez elindítja a build folyamatot és egy helyi webkiszolgálót, amely kiszolgálja az alkalmazásunkat http://localhost:4200.

Egy Angular 6 alkalmazás közvetlenül a scaffolding

A színfalak mögött az történik, hogy a CLI az összes .ts (TypeScript fájlokat) átfordítja vanilla JS-be, összegyűjti az összes szükséges függőséget a packages mappából node_modules, és az eredményt egy fájlkészletben adja ki, amelyet a 4200-as porton futó helyi webszerver szolgál ki.

Projekt fájlok

Ha nem ismered az Angular projekt mappaszerkezetét, a legfontosabb tudnivaló, hogy az alkalmazással kapcsolatos összes kód a src mappába kerül. Általában az összes modult és direktívát ebben a mappában hozod létre az alkalmazás architektúráját követve (pl. felhasználó, kosár, termék.)

Az Angular 6 projekt mappaszerkezete

Eredeti beállítás

Oké, eddig megvan az alkalmazásunk kezdeti beállítása. Kezdjünk hozzá néhány változtatáshoz.

Mielőtt elkezdenénk, ássuk be magunkat egy kicsit a src mappába. A kezdeti oldal 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>

Itt néhány alapvető HTML és a <app-root> tag látható. Ez egy Angular komponens, és ahová az Angular 6 beilleszti a komponens kódunkat.

Megtaláljuk a app/app.component.ts fájlt, amely a app-root szelektorral rendelkezik, hogy megfeleljen annak, ami a index.html fájlban van.

A komponens egy díszített TypeScript osztály, és ebben az esetben a title tulajdonságot tartalmazza. A @Component dekorátor azt mondja az Angularnak, hogy a komponens viselkedését foglalja bele az osztályba. A szelektoron kívül megadja, hogy melyik HTML fájlt renderelje és milyen stíluslapokat használjon.

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

Ha megnézzük a app.component.html-t, akkor láthatjuk a {{title}} interpolációs kötést. Itt történik az összes mágikus kötés, és az Angular rendereli az osztály title tulajdonságának értékét, és frissíti azt minden alkalommal, amikor az megváltozik.

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

Lépjünk tovább, és frissítsük az title-t az osztályból 'My Memories!'-ra.

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

Láthatjuk, hogy a fordító feldolgozza a módosításunkat, és a böngésző frissül, hogy megjelenítse a frissített címünket.

Ez azt jelenti, hogy az Angular 6 ng serve figyeli a fájlunk változásait, és minden alkalommal rendereli, amikor bármilyen fájlban változás történik.

A kódolás barátságosabbá tétele és a teljes oldalfrissítés elkerülése érdekében minden változtatás alkalmával kihasználhatjuk a webpack Hot Module Replacement (HMR) előnyeit, amely csak a JS/CSS megváltozott darabját frissíti ahelyett, hogy teljes frissítést produkálna a változtatásaink megjelenítéséhez.

A HMR konfigurálása

Először is be kell állítanunk a környezetet.

Készítsünk egy src/environments/environment.hmr.ts fájlt a következő tartalommal:

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

Frissítsük a src/environments/environment.prod.ts fájlt, és adjuk hozzá a hmr: false jelzőt a környezethez:

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

Majd frissítsük a src/environments/environment.ts fájlt, és ott is adjuk hozzá a hmr: false jelzőt a környezethez:

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

Majd a angular.json fájlban frissítsük ezt a részt:

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

És a projects alatt → my-memoriesarchitectserveconfigurations:

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

Most frissítsük a tsconfig.app.json-t, hogy tartalmazza a szükséges types (nos, típusát) a compilerOptions alatt:

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

A következőkben telepítjük a @angularclass/hmr modult, mint fejlesztési függőséget:

npm install --save-dev @angularclass/hmr

Aztán konfiguráljuk egy src/hmr.ts fájl létrehozásával:

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

Következő lépésként frissítsük a src/main.ts modult, hogy a fenti függvényt használja:

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

Azt csináljuk itt, hogy a bootstrap meghív egy anonim függvényt, és ezután megkérdezzük, hogy a environment.hmr flag igaz-e. Ez a következő lépés. Ha igen, akkor meghívjuk a korábban definiált függvényt a hmr.ts-ből, amely lehetővé tette a forró modulcserét; ellenkező esetben a bootstrap-et a korábbiak szerint használjuk.

Most, amikor a ng serve --hmr --configuration=hmr-t futtatjuk, akkor a hmr konfigurációt hívjuk meg, és amikor változtatunk a fájlokon, akkor teljes frissítés nélkül kapunk frissítéseket. Az első --hmr a webpack számára, a --configuration=hmr pedig az Angular számára, hogy használja a hmr környezetet.

Progresszív webes alkalmazás (PWA)

Az Angular 6 PWA támogatás hozzáadásához és az alkalmazás offline betöltésének engedélyezéséhez használhatjuk az egyik új CLI parancsot, ng add:

ng add @angular/

Megjegyzem, hogy a verziót hozzáadom, mivel a legújabb verzió, amikor ezt a bemutatót írtam, hibát dobott. (Kipróbálhatod nélküle is, és ellenőrizheted, hogy működik-e nálad egyszerűen a ng add @angular/pwa használatával.)

Oké, tehát miután lefuttattuk a parancsot, sok változást fogunk látni a projektünkön. A legfontosabb változások, hogy hozzáadta:

  • Hivatkozás a manifest.json-re a angular.json assets fájlban, hogy az szerepeljen a build outputban, valamint "serviceWorker": true a production buildekben
  • A ngsw-config.json fájl a kezdeti beállításokkal, hogy az alkalmazás futtatásához szükséges összes fájlt gyorsítótárba helyezze
  • A manifest.json meta tag a index.html fájlban
  • A manifest.json fájl maga, az alkalmazás alapkonfigurációjával
  • A szolgáltatási munkás betöltése az alkalmazás modulban ServiceWorkerModule.register('/ngsw-worker.js', { enabled: environment.production }) (megjegyzendő, hogy a szolgáltatási munkás csak termelési környezetben lesz engedélyezve)

Ez most azt jelenti, hogy amikor a felhasználó először lép be az URL-re, a fájlok letöltődnek. Ezután, ha a felhasználó megpróbálja elérni az URL-t hálózati szolgáltatás nélkül, akkor az alkalmazás továbbra is működni fog azáltal, hogy lehúzza ezeket a gyorsítótárazott fájlokat.

A Material Angular 6 UI könyvtár hozzáadása

Ezidáig megvan a kezdeti beállítás, és készen állunk az alkalmazásunk építésének megkezdésére. A már megépített komponensek felhasználásához használhatjuk a Material Angular 6-os verzióját.

Az material csomag telepítéséhez az alkalmazásunkra ismét a ng add:

ng add @angular/material

Futtatás után látni fogjuk, hogy néhány új csomagot adtunk hozzá és néhány alapvető stíluskonfigurációt:

  • index.html tartalmazza a Roboto betűtípust és a Material ikonok
  • BrowserAnimationsModule hozzáadódik a AppModule
  • angular.json az indigó-pink témát már tartalmazza számunkra

Az előre elkészített Angular 6 téma kiválasztása

Újra kell indítanunk ng serve, hogy felvegyük a témát, Vagy választhat egy másik előre elkészített témát.

Kapcsolódóan: Ultra-modern webalkalmazások építése az Angular Material segítségével

Basic Layout

A kezdeti sidenav elrendezéshez a Materialhoz mellékelt sémákat fogjuk használni. De nem baj, ha más elrendezést szeretne használni.

(Dióhéjban, a sémák segítségével transzformációkat alkalmazhat a projektre: Szükség szerint létrehozhat, módosíthat vagy törölhet fájlokat. Ebben az esetben egy sidenav elrendezést készít az alkalmazásunkhoz.)

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

Ezzel létrehoz egy sidenav komponenst a minimális beállításokkal, készen az indításra. Hát nem nagyszerű?

Az összes szükséges modult is tartalmazta a app.module.ts-ben.

Egy újonnan létrehozott "my-nav" Angular 6 komponens

Mivel SCSS-t használunk, át kell neveznünk a my-nav.component.css fájlt my-nav.component.scss-re, és a my-nav.component.ts-ben frissíteni kell a megfelelő styleUrls hivatkozást az új név használatára.

Az új komponens használatához most menjünk a app.component.html-be, és távolítsuk el az összes kezdeti kódot, így csak:

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

Ha visszamegyünk a böngészőbe, a következőt fogjuk látni:

Négypaneles elrendezés, a bal felső sarokban Menu, mellette my-memories, a Menu alatt pedig három számozott link; a negyedik panel üres

Frissítsük a linkeket, hogy csak a kívánt két lehetőség legyen.

Először is hozzunk létre két új komponenst:

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

(A második egy anyagséma, amelyet egy táblázat létrehozására használunk.)

Következő lépésként a my-nav-ben frissítsük a linkek beállításához és a <router-outlet> beépítéséhez a <router-outlet>-t a tartalmi összetevőink megjelenítéséhez:

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

Az app.component.html-ben is frissítenünk kell, hogy csak a fő <router-outlet> (ill, távolítsuk el a <my-nav>-t):

<router-outlet></router-outlet>

Következő lépésként a AppModule-ban beillesztjük az útvonalakat:

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

Megjegyezzük, hogy a MyNavComponent-t állítjuk be szülőnek és a két általunk létrehozott komponenst gyermeknek. Ez azért van így, mert a <router-outlet>-t felvettük a MyNavComponent-ba, és amikor a két útvonal valamelyikét elérjük, a gyermekkomponenst fogjuk megjeleníteni, ahová a <router-outlet> került.

Az alkalmazás kiszolgálásakor ezt követően azt kell látnunk:

A bal oldali linkek helyébe az Add Memory és a View My Memories kerültek, az utóbbit kiválasztva. Az üres ablaktáblában most már van egy táblázat az azonosítószámokkal és nevekkel.

Az alkalmazás elkészítése (Az emlékek naplója)

Oké, most hozzuk létre az űrlapot, amellyel új emlékeket menthetünk a naplónkba.

Importálnunk kell néhány anyagmodult és az űrlapok modult a app.module.ts-ünkbe:

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

Az add-memory.component.html-ben pedig hozzáadjuk az űrlapot:

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

Itt egy mat-card-et használunk, és két mezőt adunk hozzá, egy date-et és egy textarea-et.

Megjegyezzük, hogy a -et használjuk. Ez az Angular direktíva fogja egymáshoz kötni a memory.date kifejezést és az osztályban lévő memory tulajdonságot, ahogy azt később látni fogjuk. (A szintaktikai cukor – egy rövidítés arra, hogy kétirányú adatkötést hajtsunk végre az osztályból a nézethez és a nézetből az osztályhoz. Ez azt jelenti, hogy amikor szöveget írunk be a nézetben, a memory.date tükrözi ezeket a változásokat az osztálypéldányban, és ha az osztálypéldányban módosítjuk a memory.date-t, a nézet is tükrözi a változásokat.)

A add-memory.component.ts-ben a kód így fog kinézni:

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

Itt a ngModel segítségével kötött memory tulajdonságot inicializáljuk. Amikor a AddMemoryComponent komponens példányosításra kerül, a memory egy üres objektum lesz. Ezután, amikor a ngModel direktíva fut, képes lesz hozzárendelni a bemeneti értéket a memory.date és memory.text tulajdonságokhoz. Ha ezt nem tennénk meg, akkor Cannot set property 'date/text' of undefined hibát kapnánk.

Mindeközben a add-memory.component.scss-nek rendelkeznie kell:

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

Mióta megvan a <pre> {{ memory | json }} </pre>, láthatjuk a memory aktuális állapotát a nézetben. Ha a böngészőbe lépünk, itt az eddigi eredmény:

A "my-memories" naplóalkalmazás prototípusa, a felhasználói bevitel belső reprezentációjának (dátum és szöveg.)

A nézetben az űrlapot a (ngSubmit)="onSubmit()"-en keresztül az osztályban lévő onSubmit függvényhez kötöttük.

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

A “Ments meg!” gombra kattintva tehát a konzolnaplóba küldött felhasználói bemenet belső reprezentációját kapjuk:

A felhasználói bemenet belső reprezentációja a konzolnaplóban.

Angular 6 Tutorial: Csatlakozás a Firebase-hez

A következő lépés az lesz, hogy a projektünket csatlakoztatjuk a Firebase-hez, hogy elmenthessük az emlékeinket.

Először is menjünk a Firebase konzolra, és hozzunk létre ott egy projektet.

Firebase projekt hozzáadása.

Második lépésként telepítjük a firebase és angularfire2 csomagokat:

npm install firebase angularfire2 --save

Majd mindhárom fájlba:

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

…hozzáadjuk a Firebase configunkat:

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

A fenti fájlok szükséges konfigurációs adatait a projekt áttekintő oldalán a “Firebase hozzáadása a webalkalmazáshoz” gombra kattintva kaphatjuk meg.

Ezután a Firebase modulokat beillesztjük a app.module.ts-ünkbe:

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

A add-memory.component.ts-ben pedig a konstruktorba injektáljuk az adatbázist, és az űrlap értékeinek az adatbázisba történő mentését. Ha a Firebase-től érkező push promise sikeres, akkor a konzolban naplózzuk a sikert, és visszaállítjuk a modellt:

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

A Firebase adatbázisához való írási és olvasási hozzáférés engedélyezése.

Az adatbázis szabályainál engedélyeznie kell a nyilvános hozzáférést, így a névtelen felhasználók olvashatnak és írhatnak róla. Vegye figyelembe, hogy ezzel a beállítással bármelyik felhasználó képes lesz olvasni/megváltoztatni/törölni az alkalmazás adatait. Győződjön meg róla, hogy a szabályokat ennek megfelelően állította be, mielőtt a termelésbe lép.

Azért, hogy felvegye a környezeti változásokat, újra kell indítania a ng serve folyamatot.

Most, amikor visszamegyünk a böngészőbe és rákattintunk a mentés gombra, látni fogjuk, hogy a memória hozzá lett adva az adatbázishoz:

A tesztmemóriánk hozzá lett adva a napló alkalmazásunk Firebase adatbázisához.

Nézzük meg, hogyan tudjuk lekérni az emlékeinket és megjeleníteni őket az Anyag táblázatban.

Még korábban létrehoztuk a táblázatot a ng generate @angular/material:material-table --name=view-memories', we automatically got a file view-memories/view-memories-datasource.ts` segítségével. Ez a fájl hamis adatokat tartalmaz, ezért meg kell változtatnunk, hogy a Firebase-ből kezdjük el húzni.

A view-memories-datasource.ts-ben eltávolítjuk a EXAMPLE_DATA-et, és egy üres tömböt állítunk be:

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

És a getSortedData-ben frissítjük a mezők nevét:

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

A view-memories.component.html-ben frissítjük az oszlopok nevét date-re és text-ra a memória modellünkből. Vegyük észre, hogy mivel a dátumot milliszekundum formátumban mentettük el, itt egy date pipe segítségével alakítjuk át az értéket a megjelenítéshez egy emberbarátabb dátumformátumba. Végül eltávolítjuk a ="dataSource.data.length"-et a paginátorból, mivel az adatokat aszinkron módon fogjuk betölteni a Firebase-ből:

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

A view-memories.component.css-et view-memories.component.scss-re változtatjuk, és beállítjuk a táblázat stílusát:

table{ width: 100%;}

A view-memories.component.ts-ben a styleUrls-et a fenti átnevezésnek megfelelően ./view-memories.component.scss-re módosítjuk. A displayedColumns tömböt is frissítjük -re, és beállítjuk a táblázat adatforrását, hogy adatokat kapjon a Firebase-ből.

Az történik itt, hogy feliratkozunk az emlékek listájára, és amikor megkapjuk az adatokat, akkor instanciáljuk a ViewMemoriesDataSource-t, és beállítjuk az adat tulajdonságát a Firebase-ből származó adatokkal.

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

A Firebase egy ReactiveX stílusú Observable tömböt ad vissza.

Megjegyezzük, hogy a this.db.list<ViewMemoriesItem>('memories')-at 'memories' útvonalból húzott értékeket a ViewMemoriesItem-be vetítjük. Erről a angularfire2 könyvtár gondoskodik.

Az unsubscribe hívást az Angular komponens életciklusának onDestroy kampóján belül is beépítettük.

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

Most, hogy az alkalmazásunk éles legyen, telepítsük a Firebase Hostingra. Ehhez telepítsük a Firebase CLI-t, ami elérhetővé teszi a firebase parancsot:

npm install -g firebase-tools

Most már használhatjuk a Firebase CLI-t a bejelentkezéshez:

firebase login

Ez a Google fiók kiválasztását kéri.

A következő lépésben inicializáljuk a projektet és konfiguráljuk a Firebase Hostingot:

firebase init

Egyszerűen csak a Hosting opciót választjuk ki.

A következő lépésben, amikor az elérési utat kéri, akkor a dist/my-memories értéket állítjuk be. Amikor megkérdezik, hogy egyoldalas alkalmazásként konfiguráljuk-e (azaz minden URL-t átírunk-e /index.html-re), igennel válaszolunk.”

Végül leütjük: “A dist/my-memories/index.html fájl már létezik. Overwrite?” Itt azt válaszoljuk, hogy “nem.”

Ez létrehozza a Firebase .firebaserc és firebase.json konfigurációs fájlokat a megadott konfigurációval.

Az utolsó lépés a futtatás:

ng build --prodfirebase deploy

És ezzel már publikáltuk is az alkalmazást a Firebase-re, ami egy URL-t biztosít számunkra, ahová navigálhatunk, mint például https://my-memories-b4c52.firebaseapp.com/view-memories, ahol megtekinthetjük a saját publikált demómat.

Hű, végigmentél a tutorialon! Remélem, élvezted. A teljes kódot is megnézheted a GitHubon.

One Step at a Time

Angular egy nagyon hatékony keretrendszer webes alkalmazások építéséhez. Már régóta létezik, és bizonyított kis, egyszerű és nagy, összetett alkalmazásokhoz egyaránt – az Angular 6 sem kivétel ez alól.

Az Angular a jövőben is tervezi a folyamatos fejlesztést és az új webes paradigmák követését, mint például a webkomponensek (Angular Elements). Ha hibrid alkalmazások építése érdekli, megnézheti az Ionicot, amely az Angular-t használja alapul szolgáló keretrendszerként.

Ez a bemutató nagyon alapvető lépéseket fedett le az Angular, a Material és a Firebase használatának megkezdéséhez. De figyelembe kell vennie, hogy a valós alkalmazásokhoz validációt kell hozzáadni, és hogy az alkalmazás könnyebben karbantartható és skálázható legyen, valószínűleg a legjobb gyakorlatokat szeretné követni, mint például a szolgáltatások, újrafelhasználható komponensek stb. használata. Ez egy másik cikk témája lesz – remélhetőleg ez a cikk elég volt ahhoz, hogy kedvet csináljon az Angular fejlesztéshez!

Kapcsolódó: All Perks, No Hassle: Egy Angular 9 bemutató

Leave a Reply