portaldacalheta.pt
  • Κύριος
  • Σχεδιασμός Μάρκας
  • Το Μέλλον Της Εργασίας
  • Σχεδιασμός & Πρόβλεψη
  • Σχεδιασμός Για Κινητά
Πίσω Μέρος

Διαχείριση κατάστασης σε γωνιακή χρήση του Firebase



Η διαχείριση του κράτους είναι ένα πολύ σημαντικό κομμάτι της αρχιτεκτονικής που πρέπει να λάβετε υπόψη κατά την ανάπτυξη μιας εφαρμογής ιστού.

Σε αυτό το σεμινάριο, θα εξετάσουμε μια απλή προσέγγιση για τη διαχείριση της κατάστασης σε ένα Γωνιακή εφαρμογή που χρησιμοποιεί Firebase ως το πίσω άκρο του.



Θα εξετάσουμε μερικές έννοιες, όπως πολιτεία, καταστήματα και υπηρεσίες. Ας ελπίσουμε ότι αυτό θα σας βοηθήσει να κατανοήσετε καλύτερα αυτούς τους όρους και να κατανοήσετε καλύτερα άλλες βιβλιοθήκες κρατικής διαχείρισης όπως NgRx και NgXs.



Θα δημιουργήσουμε μια σελίδα διαχειριστή υπαλλήλων για να καλύψουμε ορισμένα διαφορετικά σενάρια διαχείρισης κατάστασης και τις προσεγγίσεις που μπορούν να τα χειριστούν.



Εξαρτήματα, υπηρεσίες, Firestore και διαχείριση κατάστασης στο Angular

Σε ένα τυπικό Γωνιώδης εφαρμογή έχουμε στοιχεία και υπηρεσίες. Συνήθως, τα στοιχεία θα χρησιμεύσουν ως πρότυπο προβολής. Οι υπηρεσίες θα περιέχουν επιχειρηματική λογική ή / και επικοινωνία με εξωτερικά API ή άλλες υπηρεσίες για την ολοκλήρωση ενεργειών ή την ανάκτηση δεδομένων.

Τα στοιχεία συνδέονται με υπηρεσίες, οι οποίες συνδέονται με άλλες υπηρεσίες ή HTTP API.



Τα στοιχεία θα εμφανίζουν συνήθως δεδομένα και θα επιτρέπουν στους χρήστες να αλληλεπιδρούν με την εφαρμογή για να εκτελούν ενέργειες. Ενώ το κάνετε αυτό, τα δεδομένα ενδέχεται να αλλάξουν και η εφαρμογή αντικατοπτρίζει αυτές τις αλλαγές ενημερώνοντας την προβολή.

Η μηχανή ανίχνευσης αλλαγών της Angular φροντίζει να ελέγξει πότε έχει αλλάξει μια τιμή σε ένα στοιχείο που συνδέεται με την προβολή και ενημερώνει την προβολή αναλόγως.



Καθώς η εφαρμογή μεγαλώνει, θα αρχίσουμε να έχουμε όλο και περισσότερα στοιχεία και υπηρεσίες. Συχνά η κατανόηση του τρόπου με τον οποίο αλλάζουν τα δεδομένα και η παρακολούθηση του πού συμβαίνει μπορεί να είναι δύσκολη.

Γωνιακό και Firebase

Όταν χρησιμοποιούμε Firebase ως το πίσω μέρος μας, μας παρέχεται ένα πραγματικά τακτοποιημένο API που περιέχει τις περισσότερες από τις λειτουργίες και τη λειτουργικότητα που χρειαζόμαστε για τη δημιουργία μιας εφαρμογής σε πραγματικό χρόνο.



@angular/fire είναι η επίσημη βιβλιοθήκη Angular Firebase. Είναι ένα επίπεδο πάνω από τη βιβλιοθήκη SDK του Firebase JavaScript που απλοποιεί τη χρήση του SDK του Firebase σε μια γωνιακή εφαρμογή. Παρέχει μια καλή εφαρμογή με καλές πρακτικές Angular, όπως η χρήση Παρατηρήσιμων για τη λήψη και την εμφάνιση δεδομένων από το Firebase στα στοιχεία μας.

Τα στοιχεία εγγραφούν στο API του Firebase JavaScript μέσω @ angular / fire χρησιμοποιώντας το Observables.



Καταστήματα και πολιτεία

Μπορούμε να σκεφτούμε το 'state' ως τις τιμές που εμφανίζονται σε οποιαδήποτε δεδομένη χρονική στιγμή στην εφαρμογή. Το κατάστημα είναι απλά ο κάτοχος αυτής της κατάστασης εφαρμογής.

Η κατάσταση μπορεί να μοντελοποιηθεί ως ένα απλό αντικείμενο ή μια σειρά από αυτά, αντικατοπτρίζοντας τις τιμές της εφαρμογής.



Μια κατάσταση κράτησης καταστήματος, η οποία έχει ένα παράδειγμα παραδείγματος με μερικά απλά ζεύγη τιμών-κλειδιών για όνομα, πόλη και χώρα.

Εφαρμογή γωνιακού / Firebase Sample

Ας το δημιουργήσουμε: Πρώτον, θα δημιουργήσουμε ένα βασικό ικρίωμα εφαρμογών χρησιμοποιώντας το Angular CLI και θα το συνδέσουμε με ένα έργο Firebase.

$ npm install -g @angular/cli $ ng new employees-admin` Would you like to add Angular routing? Yes Which stylesheet format would you like to use? SCSS $ cd employees-admin/ $ npm install bootstrap # We'll add Bootstrap for the UI

Και, στις styles.scss:

// ... @import '~bootstrap/scss/bootstrap';

Στη συνέχεια, θα εγκαταστήσουμε @angular/fire:

npm install firebase @angular/fire

Τώρα, θα δημιουργήσουμε ένα έργο Firebase στο την κονσόλα Firebase .

Η κονσόλα Firebase

Στη συνέχεια, είμαστε έτοιμοι να δημιουργήσουμε μια βάση δεδομένων Firestore.

Για αυτό το σεμινάριο, θα ξεκινήσω σε δοκιμαστική λειτουργία. Εάν σκοπεύετε να κυκλοφορήσετε στην παραγωγή, θα πρέπει να εφαρμόσετε κανόνες για να απαγορεύσετε την ακατάλληλη πρόσβαση.

ο

Μεταβείτε στην Επισκόπηση έργου → Ρυθμίσεις έργου και αντιγράψτε τη διαμόρφωση ιστού Firebase στην τοπική σας environments/environment.ts.

Κενή λίστα εφαρμογών για το νέο έργο Firebase.

export const environment = { production: false, firebase: { apiKey: '', authDomain: '', databaseURL: '', projectId: '', storageBucket: '', messagingSenderId: '' } };

Σε αυτό το σημείο, έχουμε το βασικό ικρίωμα για την εφαρμογή μας. Εάν ng serve, θα λάβουμε:

Το γωνιακό ικρίωμα, λέγοντας

τι σημαίνει c corporation

Κατηγορίες βάσεων Firestore και Store

Θα δημιουργήσουμε δύο γενικές αφηρημένες τάξεις, τις οποίες στη συνέχεια θα πληκτρολογήσουμε και θα επεκτείνουμε για να δημιουργήσουμε τις υπηρεσίες μας.

Generics σας επιτρέπουν να γράφετε συμπεριφορά χωρίς δεσμευμένο τύπο. Αυτό προσθέτει επαναχρησιμοποίηση και ευελιξία στον κωδικό σας.

Γενική υπηρεσία Firestore

Για να επωφεληθούμε από τα γενικά TypeScript, αυτό που θα κάνουμε είναι να δημιουργήσουμε ένα βασικό γενικό περιτύλιγμα για το @angular/fire firestore υπηρεσία.

Ας δημιουργήσουμε app/core/services/firestore.service.ts.

Εδώ είναι ο κωδικός:

import { Inject } from '@angular/core'; import { AngularFirestore, QueryFn } from '@angular/fire/firestore'; import { Observable } from 'rxjs'; import { tap } from 'rxjs/operators'; import { environment } from 'src/environments/environment'; export abstract class FirestoreService { protected abstract basePath: string; constructor( @Inject(AngularFirestore) protected firestore: AngularFirestore, ) { } doc$(id: string): Observable { return this.firestore.doc(`${this.basePath}/${id}`).valueChanges().pipe( tap(r => { if (!environment.production) { console.groupCollapsed(`Firestore Streaming [${this.basePath}] [doc$] ${id}`) console.log(r) console.groupEnd() } }), ); } collection$(queryFn?: QueryFn): Observable { return this.firestore.collection(`${this.basePath}`, queryFn).valueChanges().pipe( tap(r => { if (!environment.production) { console.groupCollapsed(`Firestore Streaming [${this.basePath}] [collection$]`) console.table(r) console.groupEnd() } }), ); } create(value: T) { const id = this.firestore.createId(); return this.collection.doc(id).set(Object.assign({}, { id }, value)).then(_ => { if (!environment.production) { console.groupCollapsed(`Firestore Service [${this.basePath}] [create]`) console.log('[Id]', id, value) console.groupEnd() } }) } delete(id: string) { return this.collection.doc(id).delete().then(_ => { if (!environment.production) { console.groupCollapsed(`Firestore Service [${this.basePath}] [delete]`) console.log('[Id]', id) console.groupEnd() } }) } private get collection() { return this.firestore.collection(`${this.basePath}`); } }

Αυτό abstract class θα λειτουργήσει ως γενικό περιτύλιγμα για τις υπηρεσίες μας στο Firestore.

Αυτό πρέπει να είναι το μόνο μέρος όπου πρέπει να κάνουμε ένεση AngularFirestore. Αυτό θα ελαχιστοποιήσει τον αντίκτυπο όταν το @angular/fire η βιβλιοθήκη ενημερώνεται. Επίσης, εάν κάποια στιγμή θέλουμε να αλλάξουμε τη βιβλιοθήκη, θα χρειαστεί μόνο να ενημερώσουμε αυτήν την τάξη.

Πρόσθεσα doc$, collection$, create, και delete. Τυλίγουν τις μεθόδους @angular/fire και παρέχουν καταγραφή όταν το Firebase μεταδίδει δεδομένα - αυτό θα γίνει πολύ βολικό για τον εντοπισμό σφαλμάτων - και αφού δημιουργηθεί ή διαγραφεί ένα αντικείμενο.

Γενική υπηρεσία καταστήματος

Η γενική μας υπηρεσία καταστήματος θα κατασκευαστεί χρησιμοποιώντας το RxJS ’BehaviorSubject. BehaviorSubject επιτρέπει στους συνδρομητές να λάβουν την τελευταία τιμή που εκπέμπεται μόλις εγγραφούν. Στην περίπτωσή μας, αυτό είναι χρήσιμο επειδή θα μπορέσουμε να ξεκινήσουμε το κατάστημα με μια αρχική τιμή για όλα τα στοιχεία μας όταν εγγραφούν στο κατάστημα.

Το κατάστημα θα έχει δύο μεθόδους, patch και set. (Θα δημιουργήσουμε μεθόδους get αργότερα.)

Ας δημιουργήσουμε app/core/services/store.service.ts:

import { BehaviorSubject, Observable } from 'rxjs'; import { environment } from 'src/environments/environment'; export abstract class StoreService { protected bs: BehaviorSubject; state$: Observable; state: T; previous: T; protected abstract store: string; constructor(initialValue: Partial) { this.bs = new BehaviorSubject(initialValue as T); this.state$ = this.bs.asObservable(); this.state = initialValue as T; this.state$.subscribe(s => { this.state = s }) } patch(newValue: Partial, event: string = 'Not specified') { this.previous = this.state const newState = Object.assign({}, this.state, newValue); if (!environment.production) { console.groupCollapsed(`[${this.store} store] [patch] [event: ${event}]`) console.log('change', newValue) console.log('prev', this.previous) console.log('next', newState) console.groupEnd() } this.bs.next(newState) } set(newValue: Partial, event: string = 'Not specified') { this.previous = this.state const newState = Object.assign({}, newValue) as T; if (!environment.production) { console.groupCollapsed(`[${this.store} store] [set] [event: ${event}]`) console.log('change', newValue) console.log('prev', this.previous) console.log('next', newState) console.groupEnd() } this.bs.next(newState) } }

Ως γενική τάξη, θα αναβάλουμε την πληκτρολόγηση έως ότου επεκταθεί σωστά.

Ο κατασκευαστής θα λάβει την αρχική τιμή του τύπου Partial. Αυτό θα μας επιτρέψει να εφαρμόσουμε τιμές μόνο σε ορισμένες ιδιότητες της πολιτείας. Ο κατασκευαστής θα εγγραφεί επίσης στο εσωτερικό BehaviorSubject εκπομπές και να ενημερώνεται η εσωτερική κατάσταση μετά από κάθε αλλαγή.

patch() θα λάβει το newValue του τύπου Partial και θα το συγχωνεύσει με το τρέχον this.state αξία του καταστήματος. Τέλος, εμείς next() το newState και εκπέμψτε τη νέα κατάσταση σε όλους τους συνδρομητές του καταστήματος.

set() λειτουργεί πολύ παρόμοια, μόνο αυτό αντί να διορθώνει την τιμή κατάστασης, θα το θέσει στο newValue έλαβε.

Θα καταγράψουμε τις προηγούμενες και τις επόμενες τιμές της κατάστασης καθώς πραγματοποιούνται αλλαγές, οι οποίες θα μας βοηθήσουν να εντοπίσουμε τον εντοπισμό σφαλμάτων και να παρακολουθούμε εύκολα τις αλλαγές κατάστασης.

πώς να χρησιμοποιήσετε το junit στο intellij

Βάζοντας τα όλα μαζί

Εντάξει, ας δούμε όλα αυτά σε δράση. Αυτό που θα κάνουμε είναι να δημιουργήσουμε μια σελίδα υπαλλήλων, η οποία θα περιέχει μια λίστα υπαλλήλων, καθώς και μια φόρμα για την προσθήκη νέων υπαλλήλων.

Ας ενημερώσουμε app.component.html για να προσθέσετε μια απλή γραμμή πλοήγησης:

Angular + Firebase + State Management
  • Employees

Στη συνέχεια, θα δημιουργήσουμε μια βασική ενότητα:

ng g m Core

Στο core/core.module.ts, θα προσθέσουμε τις λειτουργικές μονάδες που απαιτούνται για την εφαρμογή μας:

// ... import { AngularFireModule } from '@angular/fire' import { AngularFirestoreModule } from '@angular/fire/firestore' import { environment } from 'src/environments/environment'; import { ReactiveFormsModule } from '@angular/forms' @NgModule({ // ... imports: [ // ... AngularFireModule.initializeApp(environment.firebase), AngularFirestoreModule, ReactiveFormsModule, ], exports: [ CommonModule, AngularFireModule, AngularFirestoreModule, ReactiveFormsModule ] }) export class CoreModule { }

Τώρα, ας δημιουργήσουμε τη σελίδα υπαλλήλων, ξεκινώντας από τη λειτουργική μονάδα:

ng g m Employees --routing

Στο employees-routing.module.ts, ας προσθέσουμε το employees Διαδρομή:

// ... import { EmployeesPageComponent } from './components/employees-page/employees-page.component'; // ... const routes: Routes = [ { path: 'employees', component: EmployeesPageComponent } ]; // ...

Και σε employees.module.ts, θα εισαγάγουμε ReactiveFormsModule:

// ... import { ReactiveFormsModule } from '@angular/forms'; // ... @NgModule({ // ... imports: [ // ... ReactiveFormsModule ] }) export class EmployeesModule { }

Τώρα, ας προσθέσουμε αυτές τις δύο ενότητες στο app.module.ts αρχείο:

// ... import { EmployeesModule } from './employees/employees.module'; import { CoreModule } from './core/core.module'; imports: [ // ... CoreModule, EmployeesModule ],

Τέλος, ας δημιουργήσουμε τα πραγματικά στοιχεία της σελίδας υπαλλήλων μας, καθώς και το αντίστοιχο μοντέλο, υπηρεσία, κατάστημα και κατάσταση.

ng g c employees/components/EmployeesPage ng g c employees/components/EmployeesList ng g c employees/components/EmployeesForm

Για το μοντέλο μας, θα χρειαστούμε ένα αρχείο με την ονομασία models/employee.ts:

export interface Employee { id: string; name: string; location: string; hasDriverLicense: boolean; }

Η υπηρεσία μας θα εμφανίζεται σε ένα αρχείο με την ονομασία employees/services/employee.firestore.ts. Αυτή η υπηρεσία θα επεκτείνει τη γενική FirestoreService δημιουργήθηκε στο παρελθόν και θα ορίσουμε απλώς το basePath της συλλογής Firestore:

import { Injectable } from '@angular/core'; import { FirestoreService } from 'src/app/core/services/firestore.service'; import { Employee } from '../models/employee'; @Injectable({ providedIn: 'root' }) export class EmployeeFirestore extends FirestoreService { protected basePath: string = 'employees'; }

Στη συνέχεια, θα δημιουργήσουμε το αρχείο employees/states/employees-page.ts. Αυτό θα χρησιμεύσει ως κατάσταση της σελίδας υπαλλήλων:

import { Employee } from '../models/employee'; export interface EmployeesPage { loading: boolean; employees: Employee[]; formStatus: string; }

Το κράτος θα έχει loading τιμή που καθορίζει εάν θα εμφανιστεί ένα μήνυμα φόρτωσης στη σελίδα, το employees οι ίδιοι, και ένα formStatus μεταβλητή για τη διαχείριση της κατάστασης της φόρμας (π.χ. Saving ή Saved.)

Θα χρειαστούμε ένα αρχείο στο employees/services/employees-page.store.ts. Εδώ θα επεκτείνουμε το StoreService δημιουργήθηκε πριν. Θα ορίσουμε το όνομα του καταστήματος, το οποίο θα χρησιμοποιηθεί για την αναγνώρισή του κατά τον εντοπισμό σφαλμάτων.

Αυτή η υπηρεσία θα προετοιμάσει και θα κρατήσει την κατάσταση της σελίδας υπαλλήλων. Σημειώστε ότι ο κατασκευαστής καλεί super() με την αρχική κατάσταση της σελίδας. Σε αυτήν την περίπτωση, θα ξεκινήσουμε την κατάσταση με loading=true και μια κενή σειρά υπαλλήλων.

import { EmployeesPage } from '../states/employees-page'; import { StoreService } from 'src/app/core/services/store.service'; import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class EmployeesPageStore extends StoreService { protected store: string = 'employees-page'; constructor() { super({ loading: true, employees: [], }) } }

Τώρα ας δημιουργήσουμε EmployeesService για ενσωμάτωση EmployeeFirestore και EmployeesPageStore:

ng g s employees/services/Employees

Σημειώστε ότι εγχύουμε το EmployeeFirestore και EmployeesPageStore σε αυτήν την υπηρεσία. Αυτό σημαίνει ότι το EmployeesService θα περιέχει και θα συντονίζει κλήσεις προς το Firestore και το κατάστημα για ενημέρωση της κατάστασης. Αυτό θα μας βοηθήσει να δημιουργήσουμε ένα ενιαίο API για στοιχεία για κλήση.

import { EmployeesPageStore } from './employees-page.store'; import { EmployeeFirestore } from './employee.firestore'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { Employee } from '../models/employee'; import { tap, map } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class EmployeesService { constructor( private firestore: EmployeeFirestore, private store: EmployeesPageStore ) { this.firestore.collection$().pipe( tap(employees => { this.store.patch({ loading: false, employees, }, `employees collection subscription`) }) ).subscribe() } get employees$(): Observable { return this.store.state$.pipe(map(state => state.loading ? [] : state.employees)) } get loading$(): Observable { return this.store.state$.pipe(map(state => state.loading)) } get noResults$(): Observable { return this.store.state$.pipe( map(state => { return !state.loading && state.employees && state.employees.length === 0 }) ) } get formStatus$(): Observable { return this.store.state$.pipe(map(state => state.formStatus)) } create(employee: Employee) { this.store.patch({ loading: true, employees: [], formStatus: 'Saving...' }, 'employee create') return this.firestore.create(employee).then(_ => { this.store.patch({ formStatus: 'Saved!' }, 'employee create SUCCESS') setTimeout(() => this.store.patch({ formStatus: '' }, 'employee create timeout reset formStatus'), 2000) }).catch(err => { this.store.patch({ loading: false, formStatus: 'An error ocurred' }, 'employee create ERROR') }) } delete(id: string): any { this.store.patch({ loading: true, employees: [] }, 'employee delete') return this.firestore.delete(id).catch(err => { this.store.patch({ loading: false, formStatus: 'An error ocurred' }, 'employee delete ERROR') }) } }

Ας ρίξουμε μια ματιά στον τρόπο λειτουργίας της υπηρεσίας.

Στον κατασκευαστή, θα εγγραφούμε στη συλλογή υπαλλήλων του Firestore. Μόλις το Firestore εκπέμπει δεδομένα από τη συλλογή, θα ενημερώσουμε το κατάστημα, ρυθμίζοντας loading=false και employees με την επιστρεφόμενη συλλογή της Firestore. Δεδομένου ότι έχουμε κάνει ένεση EmployeeFirestore, τα αντικείμενα που επιστρέφονται από το Firestore πληκτρολογούνται σε Employee, γεγονός που επιτρέπει περισσότερες δυνατότητες IntelliSense.

Αυτή η συνδρομή θα είναι ζωντανή ενώ η εφαρμογή είναι ενεργή, ακούει όλες τις αλλαγές και ενημερώνει το κατάστημα κάθε φορά που το Firestore μεταδίδει δεδομένα.

this.firestore.collection$().pipe( tap(employees => { this.store.patch({ loading: false, employees, }, `employees collection subscription`) }) ).subscribe()

Το employees$() και loading$() Οι συναρτήσεις θα επιλέξουν το κομμάτι της κατάστασης που θέλουμε να χρησιμοποιήσουμε αργότερα στο στοιχείο. employees$() θα επιστρέψει έναν κενό πίνακα όταν φορτώνεται η κατάσταση. Αυτό θα μας επιτρέψει να εμφανίσουμε τα κατάλληλα μηνύματα στην προβολή.

get employees$(): Observable { return this.store.state$.pipe(map(state => state.loading ? [] : state.employees)) } get loading$(): Observable { return this.store.state$.pipe(map(state => state.loading)) }

Εντάξει, οπότε τώρα έχουμε όλες τις υπηρεσίες έτοιμες και μπορούμε να δημιουργήσουμε τα στοιχεία προβολής μας. Αλλά πριν το κάνουμε αυτό, μια γρήγορη ανανέωση μπορεί να είναι χρήσιμη…

Παρατηρήσιμα RxJs και το async Σωλήνας

Τα παρατηρήσιμα επιτρέπουν στους συνδρομητές να λαμβάνουν εκπομπές δεδομένων ως ροή. Αυτό, σε συνδυασμό με το async σωλήνα, μπορεί πολύ ισχυρό.

Το async Ο σωλήνας φροντίζει να εγγραφεί σε ένα παρατηρήσιμο και να ενημερώνει την προβολή όταν εκπέμπονται νέα δεδομένα. Το πιο σημαντικό, καταργεί αυτόματα την εγγραφή όταν το στοιχείο καταστρέφεται, προστατεύοντάς μας από διαρροές μνήμης.

Μπορείτε να διαβάσετε περισσότερα για τη βιβλιοθήκη Observables και RxJs γενικά τα επίσημα έγγραφα .

Δημιουργία στοιχείων προβολής

Στο employees/components/employees-page/employees-page.component.html, θα βάλουμε αυτόν τον κωδικό:

Employees

Ομοίως, employees/components/employees-list/employees-list.component.html θα το έχει αυτό, χρησιμοποιώντας το async τεχνική σωλήνων που αναφέρεται παραπάνω:

Loading... No results {{employee.location}}
{{employee.name}}

{{employee.hasDriverLicense ? 'Can drive': ''}}

Delete

Αλλά σε αυτήν την περίπτωση θα χρειαστούμε και έναν κωδικό TypeScript για το στοιχείο. Το αρχείο employees/components/employees-list/employees-list.component.ts θα το χρειαστεί:

import { Employee } from '../../models/employee'; import { Component, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; import { EmployeesService } from '../../services/employees.service'; @Component({ selector: 'app-employees-list', templateUrl: './employees-list.component.html', styleUrls: ['./employees-list.component.scss'] }) export class EmployeesListComponent implements OnInit { loading$: Observable; employees$: Observable; noResults$: Observable; constructor( private employees: EmployeesService ) {} ngOnInit() { this.loading$ = this.employees.loading$; this.noResults$ = this.employees.noResults$; this.employees$ = this.employees.employees$; } delete(employee: Employee) { this.employees.delete(employee.id); } }

Έτσι, μεταβαίνοντας στο πρόγραμμα περιήγησης, αυτό που θα έχουμε τώρα είναι:

Μια κενή λίστα υπαλλήλων και το μήνυμα

Και η κονσόλα θα έχει την ακόλουθη έξοδο:

Συμβάντα ενημέρωσης κώδικα που δείχνουν αλλαγές με τιμές πριν και μετά.

Κοιτάζοντας αυτό, μπορούμε να πούμε ότι το Firestore έδωσε ροή στο employees συλλογή με κενές τιμές και το employees-page το κατάστημα επιδιορθώθηκε, ρύθμιση loading από true έως false.

Εντάξει, ας δημιουργήσουμε τη φόρμα για να προσθέσουμε νέους υπαλλήλους στο Firestore:

Το έντυπο εργαζομένων

Σε employees/components/employees-form/employees-form.component.html θα προσθέσουμε αυτόν τον κωδικό:

Name Please enter a Name. Choose location {{loc}} Please select a Location. Has driver license Add { status$ }

Ο αντίστοιχος κωδικός TypeScript θα εμφανίζεται σε employees/components/employees-form/employees-form.component.ts:

import { EmployeesService } from './../../services/employees.service'; import { AngularFirestore } from '@angular/fire/firestore'; import { Component, OnInit } from '@angular/core'; import { FormGroup, FormControl, Validators } from '@angular/forms'; import { Observable } from 'rxjs'; @Component({ selector: 'app-employees-form', templateUrl: './employees-form.component.html', styleUrls: ['./employees-form.component.scss'] }) export class EmployeesFormComponent implements OnInit { form: FormGroup = new FormGroup({ name: new FormControl('', Validators.required), location: new FormControl('', Validators.required), hasDriverLicense: new FormControl(false) }); locations = [ 'Rosario', 'Buenos Aires', 'Bariloche' ] status$: Observable ; constructor( private employees: EmployeesService ) {} ngOnInit() { this.status$ = this.employees.formStatus$; } isInvalid(name) async submit() { this.form.disable() await this.employees.create({ ...this.form.value }) this.form.reset() this.form.enable() } }

Η φόρμα θα καλέσει το create() μέθοδος EmployeesService. Αυτή τη στιγμή η σελίδα μοιάζει με αυτήν:

Η ίδια κενή λίστα υπαλλήλων με πριν, αυτή τη φορά με μια φόρμα για την προσθήκη ενός νέου υπαλλήλου.

Ας ρίξουμε μια ματιά στο τι συμβαίνει όταν προσθέτουμε έναν νέο υπάλληλο.

Προσθήκη νέου υπαλλήλου

Μετά την προσθήκη ενός νέου υπαλλήλου, θα δούμε την ακόλουθη έξοδο στην κονσόλα:

Συμβάντα ενημέρωσης σε συνδυασμό με συμβάντα Firestore, από το ένα έως το έξι (τοπική δημιουργία, ροή συλλογής Firestore, συνδρομή τοπικής συλλογής, δημιουργία Firestore, επιτυχία τοπικής δημιουργίας και επαναφορά κατάστασης φόρμας χρονικού ορίου τοπικής δημιουργίας.)

Αυτά είναι όλα τα συμβάντα που ενεργοποιούνται κατά την προσθήκη ενός νέου υπαλλήλου. Ας ρίξουμε μια πιο προσεκτική ματιά.

Όταν καλούμε create() θα εκτελέσουμε τον ακόλουθο κώδικα, ρυθμίζοντας loading=true, formStatus='Saving...' και το employees κενός πίνακας ((1) στην παραπάνω εικόνα).

this.store.patch({ loading: true, employees: [], formStatus: 'Saving...' }, 'employee create') return this.firestore.create(employee).then(_ => { this.store.patch({ formStatus: 'Saved!' }, 'employee create SUCCESS') setTimeout(() => this.store.patch({ formStatus: '' }, 'employee create timeout reset formStatus'), 2000) }).catch(err => { this.store.patch({ loading: false, formStatus: 'An error ocurred' }, 'employee create ERROR') })

Στη συνέχεια, καλούμε τη βασική υπηρεσία Firestore για να δημιουργήσουμε τον υπάλληλο, ο οποίος καταγράφει (4). Στην επιστροφή υποσχέσεων, ορίσαμε formStatus='Saved!' και καταγραφή (5). Τέλος, ορίσαμε ένα χρονικό όριο για να ορίσετε formStatus επιστροφή στο κενό, καταγραφή (6).

Καταγραφή συμβάντων (2) και (3) είναι τα συμβάντα που πυροδοτούνται από τη συνδρομή Firestore στη συλλογή υπαλλήλων. Όταν το EmployeesService είναι instantiated, εγγραφούμε στη συλλογή και λαμβάνουμε τη συλλογή σε κάθε αλλαγή που συμβαίνει.

Αυτό ορίζει μια νέα κατάσταση στο κατάστημα με loading=false ορίζοντας το employees συστοιχία στους υπαλλήλους που προέρχονται από το Firestore.

Εάν επεκτείνουμε τις ομάδες καταγραφής, θα δούμε λεπτομερή δεδομένα για κάθε συμβάν και ενημέρωση του καταστήματος, με την προηγούμενη τιμή και την επόμενη, η οποία είναι χρήσιμη για τον εντοπισμό σφαλμάτων.

Η προηγούμενη έξοδος καταγραφής με όλες τις λεπτομέρειες διαχείρισης κατάστασης επεκτάθηκε.

Έτσι φαίνεται η σελίδα μετά την προσθήκη ενός νέου υπαλλήλου:

Η λίστα υπαλλήλων με μια κάρτα υπαλλήλου σε αυτήν και η φόρμα εξακολουθεί να συμπληρώνεται από την προσθήκη της.

Προσθήκη στοιχείου σύνοψης

Ας υποθέσουμε ότι τώρα θέλουμε να εμφανίσουμε ορισμένα συνοπτικά δεδομένα στη σελίδα μας. Ας υποθέσουμε ότι θέλουμε τον συνολικό αριθμό εργαζομένων, πόσοι είναι οδηγοί και πόσοι είναι από το Rosario.

ποια είναι η διαφορά μεταξύ s corp και c corp

Θα ξεκινήσουμε προσθέτοντας τις νέες ιδιότητες κατάστασης στο μοντέλο κατάστασης σελίδας στο employees/states/employees-page.ts:

// ... export interface EmployeesPage { loading: boolean; employees: Employee[]; formStatus: string; totalEmployees: number; totalDrivers: number; totalRosarioEmployees: number; }

Και θα τα προετοιμάσουμε στο κατάστημα σε employees/services/emplyees-page.store.ts:

// ... constructor() { super({ loading: true, employees: [], totalDrivers: 0, totalEmployees: 0, totalRosarioEmployees: 0 }) } // ...

Στη συνέχεια, θα υπολογίσουμε τις τιμές για τις νέες ιδιότητες και θα προσθέσουμε τους αντίστοιχους επιλογείς τους στο EmployeesService:

// ... this.firestore.collection$().pipe( tap(employees => { this.store.patch({ loading: false, employees, totalEmployees: employees.length, totalDrivers: employees.filter(employee => employee.hasDriverLicense).length, totalRosarioEmployees: employees.filter(employee => employee.location === 'Rosario').length, }, `employees collection subscription`) }) ).subscribe() // ... get totalEmployees$(): Observable { return this.store.state$.pipe(map(state => state.totalEmployees)) } get totalDrivers$(): Observable { return this.store.state$.pipe(map(state => state.totalDrivers)) } get totalRosarioEmployees$(): Observable { return this.store.state$.pipe(map(state => state.totalRosarioEmployees)) } // ...

Τώρα, ας δημιουργήσουμε το στοιχείο σύνοψης:

ng g c employees/components/EmployeesSummary

Θα το βάλουμε σε employees/components/employees-summary/employees-summary.html:

Total: { async}
Drivers: { async}
Rosario: { async}

Και σε employees/components/employees-summary/employees-summary.ts:

import { Component, OnInit } from '@angular/core'; import { EmployeesService } from '../../services/employees.service'; import { Observable } from 'rxjs'; @Component({ selector: 'app-employees-summary', templateUrl: './employees-summary.component.html', styleUrls: ['./employees-summary.component.scss'] }) export class EmployeesSummaryComponent implements OnInit { total$: Observable ; drivers$: Observable ; rosario$: Observable ; constructor( private employees: EmployeesService ) {} ngOnInit() { this.total$ = this.employees.totalEmployees$; this.drivers$ = this.employees.totalDrivers$; this.rosario$ = this.employees.totalRosarioEmployees$; } }

Στη συνέχεια, θα προσθέσουμε το στοιχείο στο employees/employees-page/employees-page.component.html:

// ...

Employees

// ...

Το αποτέλεσμα είναι το ακόλουθο:

Σελίδα υπαλλήλων, τώρα με μια περίληψη πάνω από τη λίστα, που δείχνει τον αριθμό των συνολικών υπαλλήλων, εκείνων που είναι οδηγοί και εκείνων που προέρχονται από το Rosario.

Στην κονσόλα έχουμε:

Έξοδος κονσόλας που δείχνει ένα συμβάν ενημέρωσης κώδικα που αλλάζει τις συνοπτικές τιμές.

Η υπηρεσία υπαλλήλων υπολογίζει το σύνολο totalEmployees, totalDrivers, και totalRosarioEmployees σε κάθε εκπομπή και ενημερώνει την κατάσταση.

ο Ο πλήρης κώδικας αυτού του σεμιναρίου είναι διαθέσιμος στο GitHub , και υπάρχει επίσης μια ζωντανή επίδειξη .

Διαχείριση της κατάστασης της γωνιακής εφαρμογής χρησιμοποιώντας παρατηρήσιμα… Ελέγξτε!

Σε αυτό το σεμινάριο, καλύψαμε μια απλή προσέγγιση για τη διαχείριση της κατάστασης σε εφαρμογές Angular χρησιμοποιώντας ένα Firebase back-end.

Αυτή η προσέγγιση ταιριάζει όμορφα με τις γωνιακές οδηγίες χρήσης των παρατηρήσιμων. Διευκολύνει επίσης τον εντοπισμό σφαλμάτων παρέχοντας παρακολούθηση για όλες τις ενημερώσεις στην κατάσταση της εφαρμογής.

Η γενική υπηρεσία καταστήματος μπορεί επίσης να χρησιμοποιηθεί για τη διαχείριση της κατάστασης εφαρμογών που δεν χρησιμοποιούν λειτουργίες Firebase, είτε για τη διαχείριση μόνο των δεδομένων της εφαρμογής ή των δεδομένων που προέρχονται από άλλα API.

Αλλά προτού το εφαρμόσετε αδιάκριτα, ένα πράγμα που πρέπει να λάβετε υπόψη είναι ότι EmployeesService εγγράφεται στο Firestore στον κατασκευαστή και συνεχίζει να ακούει ενώ η εφαρμογή είναι ενεργή. Αυτό μπορεί να είναι χρήσιμο εάν χρησιμοποιούμε τη λίστα υπαλλήλων σε πολλές σελίδες της εφαρμογής, για να αποφύγουμε τη λήψη δεδομένων από το Firestore κατά την πλοήγηση μεταξύ των σελίδων.

Ωστόσο, αυτή δεν μπορεί να είναι η καλύτερη επιλογή σε άλλα σενάρια, όπως εάν απλά χρειάζεται να τραβήξετε αρχικές τιμές μία φορά και, στη συνέχεια, να ενεργοποιήσετε χειροκίνητα τις επαναφορτώσεις δεδομένων από το Firebase. Η ουσία είναι ότι είναι πάντα σημαντικό να κατανοήσετε τις απαιτήσεις της εφαρμογής σας για να επιλέξετε καλύτερες μεθόδους εφαρμογής.

Κατανόηση των βασικών

Τι είναι η γωνιακή;

Το Angular (αρχικά AngularJS) είναι ένα δημοφιλές πλαίσιο front-end για τη δημιουργία εφαρμογών μιας σελίδας (SPA). Είναι ανοιχτού κώδικα και υποστηρίζεται από την Google.

Τι είναι η διαχείριση του κράτους;

Η διαχείριση της κατάστασης αφορά τη σωστή παρακολούθηση μεταβλητών σε μια εφαρμογή ιστού. Π.χ. εάν ένας χρήστης της εφαρμογής συνομιλίας άλλαξε αίθουσες συνομιλίας, αυτή είναι μια αλλαγή στην κατάσταση. Εάν έστειλαν τότε ένα μήνυμα, αλλά η δυνατότητα αποστολής δεν γνώριζε την προηγούμενη αλλαγή κατάστασης, θα έστελνε το μήνυμα στην προηγούμενη αίθουσα συνομιλίας, με αποτέλεσμα ένα πολύ κακό UX.

Τι είναι το Firebase;

Το Google Firebase είναι μια πλατφόρμα ανάπτυξης εφαρμογών για κινητά all-in-one. Είναι γνωστό για την αρχική προσφορά βάσης δεδομένων σε πραγματικό χρόνο, αλλά σήμερα περιλαμβάνει ενσωματωμένες αναφορές σφαλμάτων, έλεγχο ταυτότητας και φιλοξενία στοιχείων, μεταξύ άλλων.

Οδηγός για την εξόρυξη δεδομένων φιλική προς τον προϋπολογισμό

Πίσω Μέρος

Οδηγός για την εξόρυξη δεδομένων φιλική προς τον προϋπολογισμό
The Blues of the Food Kit Industry: Πώς μπορεί το Blue Apron να ανακάμψει από τους Bad Times;

The Blues of the Food Kit Industry: Πώς μπορεί το Blue Apron να ανακάμψει από τους Bad Times;

Διαδικασίες Χρηματοδότησης

Δημοφιλείς Αναρτήσεις
Συμβουλές για προσέλκυση, διαχείριση και διατήρηση προγραμματιστών λογισμικού
Συμβουλές για προσέλκυση, διαχείριση και διατήρηση προγραμματιστών λογισμικού
Λογισμικό ανοιχτού κώδικα - Επενδυτικό επιχειρηματικό μοντέλο ή όχι;
Λογισμικό ανοιχτού κώδικα - Επενδυτικό επιχειρηματικό μοντέλο ή όχι;
Ένας οδηγός βήμα προς βήμα για τη δημιουργία επεξηγηματικών βίντεο για κινούμενα προϊόντα
Ένας οδηγός βήμα προς βήμα για τη δημιουργία επεξηγηματικών βίντεο για κινούμενα προϊόντα
Αύξηση ανάπτυξης λογισμικού - Ένα Docker Swarm Tutorial
Αύξηση ανάπτυξης λογισμικού - Ένα Docker Swarm Tutorial
Ένας οδηγός για τη διαχείριση του συναλλαγματικού κινδύνου
Ένας οδηγός για τη διαχείριση του συναλλαγματικού κινδύνου
 
Μεγάλα δεδομένα: Συνταγή για τη φαρμακευτική έρευνα και ανάπτυξη
Μεγάλα δεδομένα: Συνταγή για τη φαρμακευτική έρευνα και ανάπτυξη
Γνωρίστε το Bond, Microsoft Bond - Ένα νέο πλαίσιο σειριοποίησης δεδομένων
Γνωρίστε το Bond, Microsoft Bond - Ένα νέο πλαίσιο σειριοποίησης δεδομένων
Τρόπος πρόσληψης συμμετεχόντων στην έρευνα UX
Τρόπος πρόσληψης συμμετεχόντων στην έρευνα UX
Πώς να κάνετε τη μετάβαση απομακρυσμένης εργασίας με ευκολία
Πώς να κάνετε τη μετάβαση απομακρυσμένης εργασίας με ευκολία
Το ApeeScape λανσάρει νέα εξειδίκευση DevOps κατ 'απαίτηση για την εξυπηρέτηση του Enterprise Shift στο Cloud
Το ApeeScape λανσάρει νέα εξειδίκευση DevOps κατ 'απαίτηση για την εξυπηρέτηση του Enterprise Shift στο Cloud
Δημοφιλείς Αναρτήσεις
  • πώς να προγραμματίσετε το c++
  • βέλτιστες πρακτικές χειρισμού σφαλμάτων javascript
  • τι είναι tdd και bdd στο agile
  • πώς να φτιάξετε ένα discord bot στο android
  • διαφορά στην εταιρεία s και c
  • οθόνη συσκευής android android studio
  • διαφορά s corp και c corp
Κατηγορίες
  • Σχεδιασμός Μάρκας
  • Το Μέλλον Της Εργασίας
  • Σχεδιασμός & Πρόβλεψη
  • Σχεδιασμός Για Κινητά
  • © 2022 | Ολα Τα Δικαιώματα Διατηρούνται

    portaldacalheta.pt