Last active
August 2, 2018 10:34
-
-
Save KarolinaCzo/32fbfab6e72205bc190a9e3a4136415c to your computer and use it in GitHub Desktop.
Example feature module with a private store and feature selectors - Angular 2/6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
I'm not sure I understand everything here correctly - but it works :P | |
The order of info flow is as follows: | |
component -> dispatcher -> actions -> reducers - > component | |
1) In 'register-page.module': | |
import { NgModule } from '@angular/core'; | |
import { CommonModule } from '@angular/common'; | |
// Import Bootstrap | |
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; | |
// Import components | |
import { RegisterPageComponent } from './register-page.component'; | |
import { RouterModule } from '@angular/router'; | |
// Import for reducers to work | |
import { StoreModule, ActionReducerMap, Action } from '@ngrx/store'; | |
import { reducers } from './register-page.reducers'; | |
@NgModule({ | |
imports: [ | |
CommonModule, | |
RouterModule, | |
StoreModule.forFeature('register', reducers) | |
], | |
declarations: [RegisterPageComponent], | |
bootstrap: [RegisterPageComponent], | |
exports: [RegisterPageComponent] | |
}) | |
export class RegisterPageModule {} | |
2) In 'register-page.component': | |
import { Component, OnInit } from '@angular/core'; | |
// Import Store | |
import { Store } from '@ngrx/store'; | |
// Import Observable | |
import { Observable } from 'rxjs'; | |
// Import dispatcher | |
import { RegisterPageDispatcher } from './register-page.dispatcher'; | |
// Import State from reducers | |
import { RegisterPageState, getCounter } from './register-page.reducers'; | |
@Component({ | |
selector: 'app-register-page', | |
templateUrl: './register-page.component.html', | |
styleUrls: ['./register-page.component.scss'], | |
providers: [RegisterPageDispatcher] // A provider is an instruction on how to obtain a value for a dependency | |
}) | |
export class RegisterPageComponent implements OnInit { | |
counter$: Observable<number>; // Create an Observable that will start listening to changes | |
constructor( | |
private store: Store<RegisterPageState>, // Pass the component state | |
private dispatcher: RegisterPageDispatcher // Pass the dispatcher that will call the Actions | |
) { | |
this.counter$ = this.store.select(getCounter); // Update the conuter$ with 'getCounter' from reducers | |
} | |
increment() { | |
this.dispatcher.dispatchIncrement(); // Dispatch an action - increment from dispatcher | |
} | |
decrement() { | |
this.dispatcher.dispatchDecrement(); // Dispatch an action - decrement from dispatcher | |
} | |
ngOnInit() {} | |
} | |
3) In 'register-page.dispatcher': | |
// Import store | |
import { Store } from '@ngrx/store'; | |
// Import State from reducers | |
import { RegisterPageState } from './register-page.reducers'; | |
// Import Injectable | |
import { Injectable } from '@angular/core'; | |
// Import Actions from actions | |
import { | |
IncrementNumberAction, | |
DecrementNumberAction | |
} from './register-page.actions'; | |
@Injectable() | |
export class RegisterPageDispatcher { | |
constructor(private store: Store<RegisterPageState>) {} | |
dispatchIncrement() { | |
this.store.dispatch(new IncrementNumberAction()); | |
} | |
dispatchDecrement() { | |
this.store.dispatch(new DecrementNumberAction()); | |
} | |
} | |
4) In 'register-page.actions': | |
import { Action } from '@ngrx/store'; | |
// Create variables to be sure that the names of actions are always the same | |
export const INCREMENT = 'INCREMENT'; | |
export const DECREMENT = 'DECREMENT'; | |
// Create actions | |
export class IncrementNumberAction implements Action { | |
readonly type = INCREMENT; | |
} | |
export class DecrementNumberAction implements Action { | |
readonly type = DECREMENT; | |
} | |
export type RegisterPageActions = IncrementNumberAction | DecrementNumberAction; | |
5) In 'register-page.reducers': | |
// Import for reducers to work | |
import { | |
StoreModule, | |
ActionReducerMap, | |
Action, | |
ActionReducer, | |
createFeatureSelector, | |
createSelector | |
} from '@ngrx/store'; | |
// Import actions | |
import { | |
INCREMENT, | |
DECREMENT, | |
RegisterPageActions | |
} from './register-page.actions'; | |
// Define a feature state | |
export interface RegisterPageState { | |
counter: number; | |
} | |
// Create a feature state selector | |
export const selectFeature = createFeatureSelector<RegisterPageState>( | |
'register' | |
); | |
// Create a selector for the counter (to update it) | |
export const getCounter = createSelector(selectFeature, state => state.counter); | |
// Create a reducer | |
export const counterReducer: ActionReducer<number> = ( | |
state: number = 0, | |
action: Action | |
) => { | |
switch (action.type) { | |
case INCREMENT: | |
return state + 1; | |
case 'DECREMENT': | |
return state - 1; | |
default: | |
return state; | |
} | |
}; | |
// Update the counter with the curent state | |
export const reducers: ActionReducerMap<RegisterPageState> = { | |
counter: counterReducer | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment