Skip to content

Instantly share code, notes, and snippets.

@Hotell
Last active July 27, 2017 04:07
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save Hotell/1d1f78e9f9b6f907c793da6930dbdd4a to your computer and use it in GitHub Desktop.
Save Hotell/1d1f78e9f9b6f907c793da6930dbdd4a to your computer and use it in GitHub Desktop.
@ngrx/store integration with ngMetadata/Angular 1
import { Store } from 'ngrx-one/store';
import { INCREMENT, DECREMENT, RESET } from './counter';
interface AppState {
counter: number;
}
@Component({
selector: 'my-app',
template: `
<button (click)="increment()">Increment</button>
<div>Current Count: {{ counter | async }}</div>
<button (click)="decrement()">Decrement</button>
`
})
export class AppComponent {
counter: Observable<number>;
constructor(public store: Store<AppState>){
this.counter = store.select('counter');
}
increment(){
this.store.dispatch({ type: INCREMENT });
}
decrement(){
this.store.dispatch({ type: DECREMENT });
}
reset(){
this.store.dispatch({ type: RESET });
}
}
import { bootstrap } from 'ng-metadata/platform';
import { provideStore } from 'ngrx-one/store';
import { reducers } from './reducers';
import { AppComponent } from './app.component';
bootstrap( AppComponent, [ provideStore(reducers) ] );
export { Store, provideStore } from './providers';
import { Reducer } from '@ngrx/store/reducer';
import { Dispatcher } from '@ngrx/store/dispatcher';
import { Store } from '@ngrx/store/store';
import { State } from '@ngrx/store/state';
import { combineReducers } from '@ngrx/store/utils';
import { OpaqueToken, Injectable } from 'ng-metadata/core';
// ngMetadata doesn't support currently string objects, so for now we have to stay with traditional OpaqueToken
export const INITIAL_REDUCER = new OpaqueToken('Token ngrx/store/reducer');
export const INITIAL_STATE = new Opaquetoken('Token ngrx/store/initial-state');
// ngMetadata needed annotations
@Injectable()
class NgOneDispatcher extends Dispatcher{}
@Injectable()
class NgOneStore extends Store{}
@Injectable()
class NgOneState extends State{}
@Injectable()
class NgOneReducer extends Reducer{}
const dispatcherProvider = {
provide: NgOneDispatcher,
useFactory() {
return new Dispatcher();
}
};
const storeProvider = {
provide: NgOneStore,
deps: [NgOneDispatcher, NgOneReducer, NgOneState, INITIAL_STATE],
useFactory(dispatcher: Dispatcher, reducer: Reducer, state$: State<any>, initialState: any) {
return new Store<any>(dispatcher, reducer, state$, initialState);
}
};
const stateProvider = {
provide: NgOneState,
deps: [INITIAL_STATE, NgOneDispatcher, NgOneReducer],
useFactory(initialState: any, dispatcher: Dispatcher, reducer: Reducer) {
return new State(initialState, dispatcher, reducer);
}
};
const reducerProvider = {
provide: NgOneReducer,
deps: [ NgOneDispatcher, INITIAL_REDUCER ],
useFactory(dispatcher: Dispatcher, reducer: any) {
return new Reducer(dispatcher, reducer);
}
};
export function provideStore(reducer: any, initialState?: any): any[] {
return [
{
provide: INITIAL_REDUCER,
useFactory() {
if (typeof reducer === 'function') {
return reducer;
}
return combineReducers(reducer);
}
},
{
provide: INITIAL_STATE,
deps: [ INITIAL_REDUCER ],
useFactory(reducer) {
if (initialState === undefined) {
return reducer(undefined, { type: Dispatcher.INIT });
}
return initialState;
}
},
dispatcherProvider,
storeProvider,
stateProvider,
reducerProvider
];
}
// now export store for ngMetadata DI
export { NgOneStore as Store };
@jamesbrobb
Copy link

@Hotell i've seen your comment on this issue (ngrx/store#98), so does this no longer work?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment