In your console (in your web project directory), run the following command. This will add the dependencies to your package.json.
npm install @ngrx/core @ngrx/store @ngrx/effects --save
First create the store folders needed under your core module. Here is an example of what your structure might look like.
/src
+-- app
| +-- core
| | +-- components
| | // core components go here
| | +-- services
| | // core services go here
| | +-- store
| | | +-- actions
| | | | +-- index.ts
| | | | +-- menu.actions.ts
| | |
| | | +-- effects
| | | | +-- index.ts
| | | | +-- menu.effects.ts
| | |
| | | +-- reducers
| | | | +-- index.ts
| | | | +-- menu.reducer.ts
| | |
| | | +-- selectors
| | | | +-- index.ts
| | | | +-- menu.selector.ts
| | |
| | +-- core.module.ts
| |
| +-- app.component.html
| +-- app.component.scss
| +-- app.component.ts
| +-- app.module.ts
| +-- app.routing.module.tsIf you have no actions yet then you can leave the index.ts file blank. If you do have actions, all actions should be exported here.
export * from './menu.actions';If you have no effects yet you should still export empty effects so we can import it later.
export const effects: any[] = [];If you have any effects and as you create effects add them to the array.
import { MenuEffects } from './menu.effects';
export const effects: any[] = [
MenuEffects
];Take note of the export. It is a variable called effects. We will use that later.
Same as effects, if you do not have a reducer we will create an empty state so we can add to it later. (note: we will disable the tslint rule to allow for an empty interface)
import { ActionReducerMap, ActionReducer, MetaReducer } from '@ngrx/store';
import { environment } from '../../../../environments/environment';
import { storeFreeze } from 'ngrx-store-freeze';
// tslint:disable-next-line:no-empty-interface
export interface CoreState { }
export const reducers: ActionReducerMap<CoreState> = {};
export function logger(reducer: ActionReducer<CoreState>): ActionReducer<CoreState> {
return function(state: CoreState, action: any): CoreState {
console.log('state', state);
console.log('action', action);
return reducer(state, action);
};
}
export const metaReducers: MetaReducer<CoreState>[] = !environment.production ? [logger] : [];If you have a reducer already you can add it to the CoreState.
import { ActionReducerMap, ActionReducer, MetaReducer } from '@ngrx/store';
import { environment } from '../../../../environments/environment';
import { storeFreeze } from 'ngrx-store-freeze';
import { MenuState, menuReducer } from './menu.reducer';
export interface CoreState {
menu: MenuState;
}
export const reducers: ActionReducerMap<CoreState> = {
menu: menuReducer,
};
export function logger(reducer: ActionReducer<CoreState>): ActionReducer<CoreState> {
return function(state: CoreState, action: any): CoreState {
console.log('state', state);
console.log('action', action);
return reducer(state, action);
};
}
export const metaReducers: MetaReducer<CoreState>[] = !environment.production ? [logger] : [];Take note of the export. They are variables called reducers and metaReducers. We will use them later.
If you have no selectors yet then you can leave the index.ts file blank. If you do have selectors, all selectors should be exported here.
export * from './menu.selectors';We have one more index.ts file and that is at the root /store folder. It should export all the code we have above.
export * from './actions';
export * from './effects';
export * from './reducers';
export * from './selectors';We need to add a couple lines into our module to get the store wired up properly.
First we need to import the variables we exported earlier.
import { reducers, metaReducers, effects } from './store';Then import the @ngrx/store modules.
import { EffectsModule } from '@ngrx/effects';
import { StoreModule } from '@ngrx/store';Finally we need to import the NgModules into our Core NgModule.
@NgModule({
imports: [
CommonModule,
RouterModule,
HttpClientModule,
SharedModule,
// These two lines
StoreModule.forRoot(reducers, { metaReducers: metaReducers }),
EffectsModule.forRoot(effects),
KbxlCoreModule.forRoot(environment)
],
declarations: [...],
providers: [...],
...
})For this example, lets assume our feature is named User.
First create the store folders needed under your user module like we did with Core. Here is an example of what your structure might look like.
/src
+-- app
| +-- user
| | +-- components
| | // user components go here
| | +-- services
| | // user services go here
| | +-- store
| | | +-- actions
| | | | +-- index.ts
| | | | +-- user-search.actions.ts
| | |
| | | +-- effects
| | | | +-- index.ts
| | | | +-- user-search.effects.ts
| | |
| | | +-- reducers
| | | | +-- index.ts
| | | | +-- user-search.reducer.ts
| | |
| | | +-- selectors
| | | | +-- index.ts
| | | | +-- user-search.selector.ts
| | |
| | +-- user.module.tsIf you have no actions yet then you can leave the index.ts file blank. If you do have actions, all actions should be exported here.
export * from './user-search.actions';If you have no effects yet you should still export empty effects so we can import it later.
export const effects: any[] = [];If you have any effects and as you create effects add them to the array.
import { UserSearchEffects } from './user-search.effects';
import { UserEffects } from './user.effects';
export const effects: any[] = [
UserSearchEffects,
UserEffects
];Take note of the export. It is a variable called effects. We will use that later.
Same as effects, if you do not have a reducer we will create an empty state so we can add to it later. (note: we will disable the tslint rule to allow for an empty interface)
import { ActionReducerMap, createFeatureSelector } from '@ngrx/store';
// tslint:disable-next-line:no-empty-interface
export interface UserFeatureState {}
export const reducers: ActionReducerMap<UserFeatureState> = {};
export const getUserFeatureState = createFeatureSelector<UserFeatureState>('user');If you have a reducer(s) already you can add it to the UserState.
import { ActionReducerMap, createFeatureSelector } from '@ngrx/store';
import { UserSearchState, UserSearchReducer } from './user-search.reducer';
import { UserState, UserReducer } from './user.reducer';
export interface UserFeatureState {
userSearch: UserSearchState;
user: UserState;
}
export const reducers: ActionReducerMap<UserFeatureState> = {
userSearch: UserSearchReducer,
user: UserReducer
};
export const getUserFeatureState = createFeatureSelector<UserFeatureState>('user');Take note of the export. There is a variable called reducers. We will use it later.
If you have no selectors yet then you can leave the index.ts file blank. If you do have selectors, all selectors should be exported here.
export * from './user.selectors';
export * from './user-search.selectors';We have one more index.ts file and that is at the root /store folder. It should export all the code we have above.
export * from './actions';
export * from './effects';
export * from './reducers';
export * from './selectors';We need to add a couple lines into our module to get the store wired up properly.
First we need to import the variables we exported earlier.
import { effects, reducers } from './store';Then import the @ngrx/store modules.
import { EffectsModule } from '@ngrx/effects';
import { StoreModule } from '@ngrx/store';Finally we need to import the NgModules into our User NgModule.
@NgModule({
imports: [
UserRouterModule,
SharedModule,
// These two lines
EffectsModule.forFeature(effects),
StoreModule.forFeature('user', reducers)
],
declarations: [...],
providers: [...]
})