Outils pour utilisateurs

Outils du site


web:javascript:angular:ngrx

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
web:javascript:angular:ngrx [2018/04/22 02:30] – [The Store] sgariepyweb:javascript:angular:ngrx [2022/02/02 00:42] (Version actuelle) – modification externe 127.0.0.1
Ligne 10: Ligne 10:
  
  
 +
 +
 +====== Introduction ======
 +
 +{{:web:javascript:angular:ngrx-intro.jpg|}}
 +
 +
 +====== Composition de l'état par module ======
 +
 +
 +Dans AppModule, on utilise ''StoreModule.forRoot()'':
 +
 +<code javascript>
 +import { StoreModule } from '@ngrx/store';
 +
 +@NgModule({
 +  imports: [
 +    BrowserModule,
 +    RouterModule.forRoot(appRoutes),
 +    ...
 +    StoreModule.forRoot(reducer),
 +  ],
 +  declarations: [...],
 +  bootstrap: [ AppComponent ]
 +});
 +
 +export class AppModule {}
 +</code>
 +
 +Dans un module **feature**, on utilise ''StoreModule.forFeature()'': 
 +
 +<code javascript>
 +import { StoreModule } from '@ngrx/store';
 +
 +@NgModule({
 +  imports: [
 +    SharedModule,
 +    RouterModule.forChild(productRoutes),
 +    ...
 +    StoreModule.forFeature('products', reducer),
 +  ],
 +  declarations: [...],
 +  providers: [ ... ]
 +});
 +
 +export class ProductModule {}
 +</code>
 ====== Actions ====== ====== Actions ======
  
Ligne 81: Ligne 128:
  
 <code javascript> <code javascript>
 +import { Component, OnInit } from '@angular/core';
 +import { CompanyService } from '../company.service';
 +import { Observable } from 'rxjs/Observable';
 +import { Store } from '@ngrx/store';
 +import { Company } from '../../models';
 +import { AppState } from 'app/models/appState';
 +import * as companyAcitons from './../../actions/company.actions';
  
 +@Component({
 +  selector: 'app-company-list',
 +  templateUrl: './company-list.component.html',
 +  styleUrls: ['./company-list.component.scss'],
 +})
 +export class CompanyListComponent implements OnInit {
 +
 +  companies$: Observable<Company[]>;
 +
 +  constructor(private store: Store<AppState>) { }
 +
 +  ngOnInit() {
 +    this.loadCompanies();
 +    this.companies$ = this.store.select(state => state.companies.companies);
 +  }
 +
 +  loadCompanies() {
 +    this.store.dispatch(new companyAcitons.LoadCompaniesAction());
 +  }
 +
 +  deleteCompany(companyId: number) {
 +    this.store.dispatch(new companyAcitons.DeleteCompanyAction(companyId));
 +  }
 +}
 </code> </code>
  
 +''AppState''est une interface:
  
 +<code javascript>
 +import { Company } from './company';
  
 +export interface AppState {
 +    companies: { companies: Company[] }
 +}
 +</code>
  
 +on peut créer une interface avec ''ng g interface models/appState''.
  
  
Ligne 92: Ligne 178:
  
  
 +Fichier ''company.effects.ts'':
 +
 +<code javascript>
 +import { Injectable } from '@angular/core';
 +import { Actions, Effect, toPayload } from '@ngrx/effects';
 +import 'rxjs/add/operator/switchMap';
 +
 +import { CompanyService } from '../company/company.service';
 +import * as companyActions from './../actions/company.actions';
 +import { DeleteCompanySuccessAction } from '../actions/company.actions';
 +
 +@Injectable()
 +export class CompanyEffects {
 +    constructor(
 +        private actions$: Actions,
 +        private companyService: CompanyService
 +    ) { }
 +
 +    @Effect() loadCompanies$ = this.actions$
 +        .ofType(companyActions.LOAD_COMPANIES)
 +        .switchMap(() => {
 +            return this.companyService.loadCompanies()
 +                .map(companies => new companyActions.LoadCompaniesSuccessAction(companies));
 +        });
 +
 +    @Effect() deleteCompany$ = this.actions$
 +        .ofType(companyActions.DELETE_COMPANY)
 +        .switchMap((action: companyActions.DeleteCompanyAction) => {
 +            return this.companyService.deleteCompany(action.payload)
 +                .map(company => new companyActions.DeleteCompanySuccessAction(company.id));
 +        });
 +};
 +</code>
 +
 +
 +<code>
 +@Effect({ dispatch: false })
 +</code>
 +
 +Lancer une seule requête lors de plusieurs appels d'action ''FETCH'':
 +
 +<code javascript>
 +@Effect()
 +  request$: Observable<Action> = this.actions$.pipe(
 +    ofType<Request>(RequestTypes.REQUEST_FETCH),
 +    distinct(
 +      () => RequestTypes.REQUEST_FETCH,
 +      this.actions$.pipe(
 +        ofType<Request>(
 +          RequestTypes.REQUEST_SUCCESS,
 +          RequestTypes.REQUEST_FAILED
 +        )
 +      )
 +    ),
 +    mergeMap(action =>
 +      this.someService.request(action.data).pipe(
 +        map(data => {
 +</code>
 +
 +
 +====== Change detection Strategies ======
 +
 +
 +<code javascript>
 +@Component({
 +  selector: 'app-company-list',
 +  templateUrl: './company-list.component.html',
 +  styleUrls: ['./company-list.component.scss'],
 +  changeDetection: ChangeDetectionStrategy.OnPush
 +})
 +</code>
 +
 +
 +====== Dispatching Actions ======
 +
 +Le //lancement// d'actions se fait avec le store.  Dans le constructeur d'un composant ou d'un service, on injecte le Store:
 +
 +<code javascript>
 +constructor(private store: Store<IProduct[]>) {}
 +</code>
 +
 +Par la suite, on peut lancer des actions:
 +
 +<code javascript>
 +this.store.dispatch(new ProductsFetch());
 +</code>
 +
 +
 +
 +
 +====== Sélecteurs ======
 +
 +L'exemple ci-dessous montre comment créer un sélecteur et aussi comment faire de la composition de sélecteurs.
 +
 +<code javascript>
 +interface IRequestState {
 +  pending: boolean;
 +  success: boolean;
 +  error: any;
 +}
 +
 +export const someRequestSelector: MemoizedSelector<any, IHttpState> = createSelector(
 +  AppSelectors.appSelector(),
 +  (state: any) => state && state.someRequest
 +);
 +
 +export const requestSuccess: MemoizedSelector<
 +  IHttpState,
 +  boolean
 +> = createSelector(
 +  someRequestSelector,
 +  (request: IRequestState) => request && request.success
 +);
 +</code>
 +
 +Le sélecteur ''someRequestSelector'' est repris dans le sélecteur ''requestSuccess'' pour éviter de reprendre tout l'état à partir de ''AppSelectors.appSelector()''.
  
 +  * [[https://blog.angularindepth.com/ngrx-parameterized-selector-e3f610529f8|Parameterized Selectors]]
  
  
Ligne 99: Ligne 302:
   * [[https://toddmotto.com/redux-typescript-store|Finally understand Redux by building your own Store]]   * [[https://toddmotto.com/redux-typescript-store|Finally understand Redux by building your own Store]]
   * [[https://github.com/duncanhunter/ngrx-play-by-play|Play-by-play ngrx]]   * [[https://github.com/duncanhunter/ngrx-play-by-play|Play-by-play ngrx]]
 +  * [[https://blog.angularindepth.com/ngrx-tips-tricks-69feb20a42a7|NgRx: tips & tricks]]
web/javascript/angular/ngrx.1524357016.txt.gz · Dernière modification : 2022/02/02 00:43 (modification externe)