27 Jul

Fast bei allen Angular Projekten werden Daten von einer Componente an die andere übergeben.  

Bei kleineren Projekten kann dies über @Output, @Input und das Template geschehen. Bei einem etwas größerem Projekt, bei dem Daten von einer Componente an verschiedene andere weitergegeben werden sollen ist dies nicht praktikabel und wird schnell zu unübersichtlich. 
In einem solchen Fall komm NgRx zum tragen.. 

Redux

Was ist Redux? 
 
Im Store wird der gesamte Anwendungsstatus abgelegt. Wie zum Beispiel, ob ein Ladebalken angezeigt werden soll. Oder aber Daten, die wir aus einer Datenbank geladen haben.  
Komponenten und Services können direkt miteinander kommunizieren. Benötigen sie jedoch Daten aus dem Store, so werden diese über Actions und Reducers abgeholt.  
Im Moment lässt sich dies nur schwer nachvollziehen.  
Wir fangen einfach mal an und bauen uns ein Projekt: 

ng new ngrx-storage-example 
cd ngrx-storage-example 

Nun installieren wie den NgRx Store: 
npm install –save @ngrx/store
und rxjs
npm install –save install rxjs

Mit ng serve starten wir unsere Anwendung und sollten rufen diese im Browser unter http://localhost:4200 auf und sollten folgendes zu Gesicht bekommen:

Für unser fiktives kleines Projekt erlauben wir Benutzern, sowohl einen Namen als auch eine URL eines Tutorials mit einem einfachen Formular einzureichen. 
Wir werden diese Daten nicht in einer Datenbank speichern, da dies den Umfang dieses Tutorials zu sehr erweitern würde. Wir wollen uns nur auf Ngrx / store konzentrieren. 
Da wir zwei Daten speichern möchten (im Stil eines Arrays von Objekten), definieren wir zunächst ein Modell. 
 Erstellen Sie den folgenden Ordner und die folgende Datei: /src/app/models/tutorial.model.ts und platzieren Sie den folgenden Code darin: 

export interface Tutorial {
name: string;
url: string;
}

Damit haben wir unser Model fertig 

Nun kommt unsere Action an die Reihe: 
Eine Aktion in Ngrx / store besteht aus zwei Dingen: 

Ein Typ in Form einer Zeichenfolge. Es beschreibt, was passiert. 

Es enthält eine optionale Nutzlast von Daten. 

Stellen Sie sich eine Aktion als Ihren Postboten vor, der Ihnen die Nachricht “Hey, fügen Sie dieses Paket zu Ihrem Regal hinzu.” Es liegt an Ihnen, zu bestimmen, wo und wie Sie dieses Paket hinzufügen, das als Reduzierer bezeichnet wird (wir werden in Kürze darauf zurückkommen). 

Erstellen Sie den folgenden Ordner und die folgende Datei: /src/app/actions/tutorial.actions.ts mit folgendem Inhalt: 

// Alle benötigten imports
import { Injectable } from '@angular/core'
import { Action } from '@ngrx/store'
import { Tutorial } from './../models/tutorial.model'

// Hier definieren wir die Art der Aktion, also als String
export const ADD_TUTORIAL = '[TUTORIAL] Add'
export const REMOVE_TUTORIAL = '[TUTORIAL] Remove'

// Wir erstellen für jede Aktion eine Klasse mit einem Konstruktor, mit dem wir die Nutzdaten übergeben können. Dies ist kein erforderlicher Schritt, bietet Ihnen jedoch eine starke Eingabe.
export class AddTutorial implements Action {
readonly type = ADD_TUTORIAL
constructor(public payload: Tutorial) {}
}

export class RemoveTutorial implements Action {
readonly type = REMOVE_TUTORIAL
constructor(public payload: number) {}
}

// Wir exportieren alle unsere Aktionsklassen zur Verwendung in unserem kommenden Reduzierer.
export type Actions = AddTutorial | RemoveTutorial

Jetzt erstellen wir einen Reducer: 
 
Jetzt, da wir ein Modell und unsere Aktionen haben, müssen wir einen Reduzierer erstellen. Ein Reduzierer ist das, was die eingehende Aktion ausführt und entscheidet, was damit zu tun ist. Es nimmt den vorherigen Status an und gibt basierend auf der angegebenen Aktion einen neuen Status zurück. 

Erstellen Sie den folgenden Ordner und die folgende Datei: /src/app/reducers/tutorial.reducer.ts mit folgendem Inhalt: 

import { Action } from '@ngrx/store' 
import { Tutorial } from './../models/tutorial.model' 
import * as TutorialActions from './../actions/tutorial.actions' 

 
// Hier definieren wir einen Anfangs- oder Standardzustand. Dies ist nicht erforderlich, wenn Sie keinen sofort einsatzbereiten Status definieren möchten.  
const initialState: Tutorial = { 
     name: 'Initial Tutorial', 
     url: 'http://google.com' 
}
// Dies ist unser eigentlicher Reduzierer. Es nimmt einen Status an, den wir als Tutorial-Typ definieren, und wir haben ihn optional an initialState gebunden. Es nimmt auch die Aktion aus unserer Datei /actions/tutorial.actions auf.  
export function reducer(state: Tutorial[] = [initialState], action: TutorialActions.Actions) {
    switch(action.type) { 
        case TutorialActions.ADD_TUTORIAL: 
            return [...state, action.payload]; 
        default: 
            return state; 
    } 

 

Falls der action.type in keinem Fall übereinstimmt, gibt er einfach den Status zurück, wie im ersten Parameter unseres Reduzierers angegeben. 

Der App-Status

Keine Sorge, wir sind fast fertig mit der Einrichtung. Als letztes müssen wir einen App-Status definieren. 

Erstellen Sie die folgende Datei: /src/app/app.state.ts: 
import { Tutorial } from './models/tutorial.model'; 
export interface AppState { 
  readonly tutorial: Tutorial[]; 
}

Wir werden diese Datei in die Komponenten importieren, auf die wir auf ngrx zugreifen möchten. 
 
Anpassungen an App.Module 
 

Wir müssen @ngrx/store und unseren Reducer importieren. 

Öffnen Sie /src/app/app.module.ts und ändern Sie Folgendes: 

// …. 

import { StoreModule } from '@ngrx/store'; 
import { reducer } from './reducers/tutorial.reducer'; 
 @NgModule({ 
  // … 
  imports: [ 
    BrowserModule, 
    StoreModule.forRoot({ 
      tutorial: reducer 
    }) 
  ], 
  // ….. 

Erstellen der Componenten

Nun erstellen wir zwei Komponenten. Die eine soll Daten in unseren Storage schreiben und die andere wieder lesen: 
 
ng g c lesen 
ng g c schreiben 

Lesen aus dem Store

Öffnen der Datei /src/app/lesen/lesen.component.ts

 export class LesenComponent implements OnInit { 
  //Wir definieren beobachtbare benannte Tutorials, die wir später in der Vorlage anzeigen werden. 
  tutorials: Observable<Tutorial[]>; 
  //Wir greifen über ngrx im Konstruktor auf den Store zu und wählen dann ein Tutorial aus, das als Eigenschaft aus app.module.ts in StoreModule.forRoot ({}) definiert ist. Dies ruft den Tutorial-Reduzierer auf und gibt den Tutorial-Status zurück. 

  constructor(private store: Store<AppState>) {  
    this.tutorials = store.select('tutorial'); 
  } 
    ngOnInit() {} 

Jetzt passen wir das HTML an: 
/src/app/lesen/lesen.component.html  

<div class="right" *ngIf="tutorials"> 
 <h3>Tutorials</h3> 
  <ul> 
    <li *ngFor="let tutorial of tutorials | async"> 
      <a [href]="tutorial.url" target="_blank">{{ tutorial.name }}</a> 
    </li> 
  </ul> 
</div> 

Jetzt müssen wir noch die /src/app/app.component.html anpassen und fügen folgendes ein: 

<app-schreiben></app-schreiben> 
<app-lesen></app-lesen> 

Unter /src/styles.css hinterlegen wir die folgenden CSS Styles:

body, html {
margin: 0;
padding: 0;
font-family: ‘Arial’;
}
.left, .right {
float:left;
width: calc(50% – 6em);
padding: 3em;
}
input[type=”text”] {
width: 100%;
padding: 5px;
margin-bottom: 10px;
}
ul > li > button {
margin-left: 10px;
}

Nun ist die Schreiben Componenten an der Reihe:
Nachdem wir nun wissen, wie man aus Ngrx liest, schreiben wir darauf und rufen unsere ADD_TUTORIAL-Aktion auf.
Öffnen Sie /src/app/schreiben/schreiben.component.ts und importieren Sie Folgendes: 

import { Component, OnInit } from '@angular/core'; 
import { Store } from '@ngrx/store'; 
import { AppState } from './../app.state'; 
import { Tutorial } from './../models/tutorial.model' 
import * as TutorialActions from './../actions/tutorial.actions'; 
import { Observable } from 'rxjs'; 
export class SchreibenComponent implements OnInit { 
  constructor(private store: Store<AppState>) {}   

addTutorial(name, url) { 
    this.store.dispatch(new TutorialActions.AddTutorial({name: name, url: url}) ) 
  } 
  ngOnInit() { 
  } 

Der Hauptfokus liegt auf store.dispatch, das das Objekt mit einem Namen und einer URL-Eigenschaft aufnimmt. 

Öffnen Sie /src/app/schreiben/schreiben.component.html und fügen Sie Folgendes ein: 

<div class="left"> 
  <input type="text" placeholder="name" #name>  
<input type="text" placeholder="url" #url>   <button (click)="addTutorial(name.value,url.value)">Add a Tutorial</button> 
</div> 

Normalerweise würden wir dafür reaktive Formulare verwenden, aber das würde den Rahmen dieses Tutorials sprengen. 

Speichern Sie das Projekt und Sie werden Folgendes sehen: 


Genial. Wie Sie sehen können, wird unser Observale auf der rechten Seite mit Daten aktualisiert, die wir an den Ngrx Store übermittelt haben. 

Versuchen wir, eine andere Aktion auszulösen, mit der wir ein Tutorial entfernen können. 

Etwas aus dem Store entfernen 

Um uns mehr Muskelgedächtnis zu geben, entfernen wir die Tutorials per Klick. 
Öffnen Sie /src/app/lesen/lesen.component.html und ändern Sie den li teil in: 

<li *ngFor="let tutorial of tutorials | async; let i = index"> <button (click)="delTutorial(i)">X</button> <a [href]="tutorial.url" target="_blank">{{ tutorial.name }}</a> </li>

Dadurch wird der Index des aktuell angeklickten Listenelements an eine Funktion namens delTutorial () übergeben. 

Öffnen Sie lesen.component.ts und nehmen Sie folgende Einstellungen vor: 

import * as TutorialActions from './../actions/tutorial.actions'; 
// Hier fügen wir ein: 
  delTutorial(index) { 
    this.store.dispatch(new TutorialActions.RemoveTutorial(index) ) 
  } 

Dadurch wird unsere Aktion RemoveTutorial aufgerufen und der Index übergeben. 

Öffnen Sie jetzt /src/app/reducers/tutorial.reducer.ts und fügen Sie einen weiteren Fall hinzu: 

export function reducer(state: Tutorial[] = [initialState], action: TutorialActions.Actions) { 
    switch(action.type) { 
        case TutorialActions.ADD_TUTORIAL: 
            return [...state, action.payload]; 
        // Diesen Case Fall hinzufügen: 
        

case TutorialActions.REMOVE_TUTORIAL:
const index = action.payload;
return […state.slice(0, index), …state.slice(index + 1)];
        default: 
            return state; 
    } 

Wir verwenden einfach .splice, um den Status zu ändern, und geben ihn dann zurück. 
Probieren Sie es jetzt im Browser aus! Klicken Sie auf eines der Listenelemente (oder rechts davon), um es zu entfernen. 

Das ist Ngrx Store auf den Punkt gebracht. Natürlich steckt noch viel mehr dahinter, aber Sie sollten ein grundlegendes Verständnis haben

Den gesamten Quellcode findet ihr unter: https://github.com/Janaros/ngrxStorageTutorial

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.