Skip to content

Instantly share code, notes, and snippets.

@KarolinaCzo
Last active August 2, 2018 10:34
Show Gist options
  • Save KarolinaCzo/32fbfab6e72205bc190a9e3a4136415c to your computer and use it in GitHub Desktop.
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
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