2

I have several modules within my Angular2 application, that provide Services and Configuration.

Now I'd like to include the @ngrx/store which collects the available reducers from my modules.


Here's the bootstrap code:

import {OpaqueToken} from 'angular2/core'
import {provideStore} from '@ngrx/store'

export const REDUCER_TOKEN = new OpaqueToken('Reducer');

bootstrap(AppComponent, [
    provide(REDUCER_TOKEN, { useClass: Module1Reducers, multi: true }),
    provide(REDUCER_TOKEN, { useClass: Module2Reducers, multi: true }),
    // old code: provideStore({module1, module2}, {module1:{}, module2:[]})
    provideStore(/* INSERT CODE HERE */)
]);

The INSERT CODE HERE comment should be replaced with something, that uses all REDUCER_TOKEN providers.

How can I achieve that?

Benjamin M
  • 23,599
  • 32
  • 121
  • 201
  • you see `provide(REDUCER_TOKEN, ...)`? That's a provider that can be used along with `@Inject(REDUCER_TOKEN) list:MyInterface[]`. Have a look here ( http://blog.thoughtram.io/angular2/2015/11/23/multi-providers-in-angular-2.html ), section *Understanding Multi Providers*. – Benjamin M Mar 31 '16 at 09:18

1 Answers1

1

I don't see a way to pass it to provideStore() directly.

provideStore creates and returns an array of providers. My attempt is to first add the providers provideStore() creates and then in a second step override the REDUCER that depends on REDUCER_TOKEN:

bootstrap(AppComponent, [
    provide(REDUCER_TOKEN, { useClass: Module1Reducers, multi: true }),
    provide(REDUCER_TOKEN, { useClass: Module2Reducers, multi: true }),
    // add generated providers
    provideStore(),
    // override `REDUCER` provider
    provide(REDUCER, {
      deps: [REDUCER_TOKEN],
      useFactory(reducer){
        if(typeof reducer === 'function'){
          return reducer;
        }

        return combineReducers({
            "foo":reducer[0].reducerFunction, 
            "bar":reducer[1].reducerFunction
        });
      }
    }),
]);

If multiple providers are added for the same token (or type), without multi: true, then only the one added last takes effect.

Built according to this provideStore() implementation https://github.com/ngrx/store/blob/master/src/ng2.ts#L56

-- not tested --

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • 1
    Thank you! I now tested it, and it works with some small change: In `useFactory(reducer)` the `reducer` is an array: `[Module1, Module2]`. But the `combineReducers` function, will only take functions as parameter. Though for getting nice store names, you got to build an object from the `reducers` array. In the end, the parameter passed to `combineReducers` should look like this: `{"foo":reducer[0].reducerFunction, "bar":reducer[1].reducerFunction}` (where `foo` and `bar` are the store names). `...` anyways: You solved it! Thank you. – Benjamin M Apr 01 '16 at 20:55
  • 1
    Looks good, in my code I use a more dynamic solution, where I get the `name` and the `reducerFunction` from the module array. Like this: `return combineReducers(reducer.reduce((o, v) => { o[v.name] = v.reducerFunction; return o; }, {}));`. But your code is fine as well :) – Benjamin M Apr 03 '16 at 08:51
  • Great. I'll leave it as is then, your comment will stay here anyway. – Günter Zöchbauer Apr 03 '16 at 08:53