NGXSを用いた国家管理入門
NGXS is a state management pattern + library for Angular.
It acts as a single source of truth for your application's state, providing simple rules for predictable state mutations.
NGXS is modeled after the CQRS pattern popularly implemented in libraries like Redux and NgRx but reduces boilerplate by using modern TypeScript features such as classes and decorators.
初心者としてNGXsから始めることは、それがロケット科学の若干の種類であるというわけではなく、本質的に多くの資源が正しい方法でそれを学ぶために利用できるという事実のためであるという理由でありえません.
このチュートリアルでは、単純なCRUDアプリケーションをダミーの残りのAPIを消費する作成するためにNGXsと一緒に角度を使用します.
あなたが忍耐を実行している場合はすでに上にホップすることができますStackBlitz そして、我々が何をするつもりであるかについて、あなた自身を見てください.
必要条件
では始めましょう
ステップ1:角度CLIをインストールする
npm install -g @angular/cli
ORyarn add global @angular/cli
新しい角度プロジェクトを作成してみましょうng new learning-ngxs
ステップ2 : ngxsライブラリをインストールする
プロジェクトフォルダに移動
cd learning-ngxs
次に、このコマンドnpm install @ngxs/store --save
または、あなたが糸を使っているならばyarn add @ngxs/store
ステップ3 :プラグインのインストール(オプション)
@ngxs/logger-plugin --save
& @ngxs/devtools-plugin --save-dev
それぞれ.ステップ4 :モジュールのインポート
これがあなたの
app.module.ts
必要なモジュールをインポートした後にimport { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import {HttpClientModule} from '@angular/common/http';
import {FormsModule,ReactiveFormsModule} from '@angular/forms';
//For NGXS
import { NgxsModule } from '@ngxs/store';
import { NgxsLoggerPluginModule } from '@ngxs/logger-plugin';
import { NgxsReduxDevtoolsPluginModule } from '@ngxs/devtools-plugin';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { GeneralComponent } from './general/general.component';
import { AppState } from './states/app.state';
import { DesignutilityService } from './designutility.service';
@NgModule({
declarations: [
AppComponent,
GeneralComponent
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule,
FormsModule,
ReactiveFormsModule,
NgxsModule.forRoot([]), NgxsLoggerPluginModule.forRoot(), NgxsReduxDevtoolsPluginModule.forRoot()
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
ステップ5 :コンポーネントとサービスの作成
私たちの状態の内容を表示するために
ng g c general
サーバーとの対話のための' designユーティリティ'と呼ばれるサービスを作成するGET
, POST
, UPDATE
and DELETE
データ.ng g s designutility
忘れてはいけないDesignutilityService
インサイドproviders
アレイapp.module.ts
.providers: [DesignutilityService]
Step 4で述べたモジュールをすべてインポートしたことを確認してください.ステップ6 :アクションを作成する
src @ appの中に' action 'という名前の新しいフォルダを作成します
アクションフォルダ内で、新しいファイルを作成します
app.action.ts
//Here we define four actions for CRUD operations respectively
//Read
export class GetUsers {
static readonly type = '[Users] Fetch';
}
//Create
export class AddUsers {
static readonly type = '[Users] Add';
constructor(public payload: any) { }
}
//Update
export class UpdateUsers {
static readonly type = '[Users] Update';
constructor(public payload: any, public id: number, public i:number) { }
}
//Delete
export class DeleteUsers {
static readonly type = '[Users] Delete';
constructor(public id: number) { }
}
Actions can either be thought of as a command which should trigger something to happen, or as the resulting event of something that has already happened.
Each action contains a type field which is its unique identifier.
アクションは、コンポーネントからの状態への望ましい変更を行うようにディスパッチされます.
あなたはそれに気づいたかもしれない
GetUsers
, 他のすべてのアクションでは、パラメータ化されたコンストラクタを持っています.AddUsers
アクションのコンストラクタpayload
, このペイロードは、基本的に新しいユーザに関する情報を含みます.AddUsers
コンポーネントからディスパッチされます.ステップ7 :サービスとの連携
に
designutility.service.ts
, 取得するには、HTTPの呼び出しを追加し、更新、追加、およびDo項目を削除します.このチュートリアルでは、偽のAPI呼び出しを行うためのjsonplaceholderを使用しています.
import { Injectable } from '@angular/core';
import {HttpClient} from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class DesignutilityService {
constructor(private http:HttpClient) { }
fetchUsers(){
return this.http.get('https://jsonplaceholder.typicode.com/users');
}
addUsers(userData){
return this.http.post('https://jsonplaceholder.typicode.com/users',userData);
}
deleteUser(id:number){
return this.http.delete('https://jsonplaceholder.typicode.com/users/'+id);
}
updateUser(payload,id:number){
return this.http.put('https://jsonplaceholder.typicode.com/users/'+id, payload);
}
}
ステップ8 :状態を作成する
今このチュートリアルの最も重要な部分に到達しました.
src ' app内の' state 'という名前の新しいフォルダを作成します.
ステートフォルダ内で、新しいファイル名
app.state.ts
import { Injectable } from "@angular/core";
import { Action, Selector, State, StateContext } from "@ngxs/store";
import { DesignutilityService } from "../designutility.service";
import { tap } from 'rxjs/operators';
import { AddUsers, DeleteUsers, GetUsers, UpdateUsers } from "../actions/app.action";
export class UserStateModel {
users: any
}
@State<UserStateModel>({
name: 'appstate',
defaults: {
users: []
}
})
@Injectable()
export class AppState {
constructor(private _du: DesignutilityService) { }
@Selector()
static selectStateData(state:UserStateModel){
return state.users;
}
@Action(GetUsers)
getDataFromState(ctx: StateContext<UserStateModel>) {
return this._du.fetchUsers().pipe(tap(returnData => {
const state = ctx.getState();
ctx.setState({
...state,
users: returnData //here the data coming from the API will get assigned to the users variable inside the appstate
})
}))
}
@Action(AddUsers)
addDataToState(ctx: StateContext<UserStateModel>, { payload }: AddUsers) {
return this._du.addUsers(payload).pipe(tap(returnData => {
const state=ctx.getState();
ctx.patchState({
users:[...state.users,returnData]
})
}))
}
@Action(UpdateUsers)
updateDataOfState(ctx: StateContext<UserStateModel>, { payload, id, i }: UpdateUsers) {
return this._du.updateUser(payload, i).pipe(tap(returnData => {
const state=ctx.getState();
const userList = [...state.users];
userList[i]=payload;
ctx.setState({
...state,
users: userList,
});
}))
}
@Action(DeleteUsers)
deleteDataFromState(ctx: StateContext<UserStateModel>, { id }: DeleteUsers) {
return this._du.deleteUser(id).pipe(tap(returnData => {
const state=ctx.getState();
console.log("The is is",id)
//Here we will create a new Array called filteredArray which won't contain the given id and set it equal to state.todo
const filteredArray=state.users.filter(contents=>contents.id!==id);
ctx.setState({
...state,
users:filteredArray
})
}))
}
}
select ()について
Selector()
は、AppState
. users
内部に存在する配列AppState
Select()
ステップ10に示す.ステップ9:アプリの状態を文書化。モジュールです。TS
今、私たちは創造をしている
AppState
, この状態を文書化する必要があるapp.module.ts
ファイル.したがって、内部のインポート配列に移動します
app.module.ts
必要な変更を行います.NgxsModule.forRoot([AppState]), NgxsLoggerPluginModule.forRoot(), NgxsReduxDevtoolsPluginModule.forRoot()
Step 10 :コンポーネントの操作
コンポーネントは、我々が我々のケースの状態の内容をコントロールするつもりであるところからの場所です
general.component.ts
我々は、我々の基本的なCrud活動を実行していますAppState
.そのために、既存のユーザーを表示し、ユーザー情報を更新し、ユーザーを削除し、新しいユーザーを挿入するフォームを削除します
AppState
.import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder } from '@angular/forms';
import { Select, Store } from '@ngxs/store';
import { Observable } from 'rxjs';
import { AddUsers, DeleteUsers, GetUsers, UpdateUsers } from '../actions/app.action';
import { AppState } from '../states/app.state';
@Component({
selector: 'app-general',
templateUrl: './general.component.html',
styleUrls: ['./general.component.css']
})
export class GeneralComponent implements OnInit {
//Here I have used Reactive Form, you can also use Template Driven Form instead
userForm: FormGroup;
userInfo: [];
@Select(AppState.selectStateData) userInfo$: Observable<any>;
constructor(private store: Store, private fb: FormBuilder) { }
ngOnInit(): void {
this.userForm = this.fb.group({
id: [''],
name: [''],
username: [''],
email: [''],
phone: [''],
website: ['']
})
this.store.dispatch(new GetUsers());
this.userInfo$.subscribe((returnData) => {
this.userInfo = returnData;
})
}
addUser() {
this.store.dispatch(new AddUsers(this.userForm.value));
this.userForm.reset();
}
updateUser(id, i) {
const newData = {
id: id,
name: "Siddhesh Thipse",
username: "iamsid2399",
email: '[email protected]',
phone: '02138-280044',
website: 'samplewebsite.com'
}
this.store.dispatch(new UpdateUsers(newData, id, i));
}
deleteUser(i) {
this.store.dispatch(new DeleteUsers(i));
}
}
重要点
select
and store
からngxs/store
Select()
は、AppState
. DeleteUsers
パスi
パラメータとして( userid )です.i
はAppState
. 基本的なUIを作成した後
general.component.html
のようになります<div class="container-fluid">
<h2 style="text-decoration: underline;">Getting started with NGXS</h2>
<div class="row my-4">
<div class="col-md-3">
<h5 style="color: grey;">Add new user to State</h5>
<form [formGroup]="userForm" (ngSubmit)="addUser()">
<label class="form-label">ID</label>
<input type="text" class="form-control mb-2" placeholder="User ID" formControlName="id">
<label class="form-label">Name</label>
<input type="text" class="form-control mb-2" placeholder="Enter Name" formControlName="name">
<label class="form-label">Username</label>
<input type="text" class="form-control mb-2" placeholder="Enter a unique username" formControlName="username">
<label class="form-label">Email</label>
<input type="email" class="form-control mb-2" placeholder="[email protected]" formControlName="email">
<label class="form-label">Phone</label>
<input type="number" class="form-control mb-2" placeholder="Enter Contact No." formControlName="phone">
<label class="form-label">Website</label>
<input type="email" class="form-control mb-2" placeholder="Enter website name" formControlName="website">
<button type="submit" class="btn btn-primary btn-sm mt-2">Add User</button>
</form>
</div>
<div class="col-md-9">
<h5 style="color: grey;">User Information</h5>
<table class="table">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Name</th>
<th scope="col">Username</th>
<th scope="col">Email</th>
<th scope="col">Phone</th>
<th scope="col">Website</th>
<th scope="col">Update</th>
<th scope="col">Delete</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let contents of userInfo; index as i">
<th scope="row">{{contents.id}}</th>
<td>{{contents.name}}</td>
<td>{{contents.username}}</td>
<td>{{contents.email}}</td>
<td>{{contents.phone}}</td>
<td>{{contents.website}}</td>
<td><button class="btn btn-outline-warning btn-sm" (click)="updateUser(contents.id,i)"><i
class="bi bi-pencil-fill"></i></button></td>
<td><button class="btn btn-danger btn-sm" (click)="deleteUser(contents.id)"><i
class="bi bi-trash-fill"></i></button></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
それは、我々は正常に我々の角度アプリケーションでの状態管理を実装している.
今は間違いなくこれ以上のNGXsにはありますが、一度完全に基礎を理解している場合は、高度なものを学ぶのCakewalkです.
任意の提案のincase/クエリを下にコメントを自由に感じてください.
ソースコードはGithub
Reference
この問題について(NGXSを用いた国家管理入門), 我々は、より多くの情報をここで見つけました https://dev.to/siddheshthipse/beginner-s-guide-of-state-management-using-ngxs-35dnテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol