Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow EffectModule.forFeature() to accept angular injection token #1432

Closed
j-thebault opened this issue Nov 16, 2018 · 1 comment
Closed

Comments

@j-thebault
Copy link

Hello

I'm trying to create a reusable effect. This effect use some constant and a service :

@Injectable()
export class TreeNodeEffects {

constructor(private pagePrefix : string, private componentId : string , 
private actions$: Actions, private service: TreeService) {}
...
@Effect()
openNode$ = this.actions$.pipe( 
   ofType(TreeNodeActionTypes.OpenTreeNode)
   filter(((action: OpenTreeNode) => 
       action.pagePrefix == this.pagePrefix && action.componentId ==  this.componentId)),
   switchMap((action: OpenTreeNode) => {
      return this.service.loadNodeContent(action.payload.id)....

The problem is that TreeService is an abstract class and i would like to provide an implementation provided directly by my module... However, even if my module provide something like this :

@NgModule({
  imports: [
   ...
    TreeModule,
    StoreModule.forFeature(fromStore.STORE_FEATURE_NAME, fromStore.reducers, {metaReducers: fromStore.metaReducers}),
    EffectsModule.forFeature([ TreeNodeEffects , ...fromStore.effects]),
  ],

 providers : [
...
{
      provide: TreeService,
      useClass: TestCaseWorkspaceService
    }, {
      provide : TreeNodeEffects,
      useFactory : (actions$, service) => {
        return [new TreeNodeEffects(TEST_CASE_WORKSPACE_ROOT_URL, MAIN_TREE_ID, actions$, service)];
      },
      deps : [Actions, TreeService],
    }

The instanciation of the TreeNodeEffects fail on injection of the abstract service, angular is not able to provide the concrete implementation. The others dependencies are correctly injected. However, if i change the constructor of the effect to the concrete class, the injection is done but it make my effect hard bound to the concrete type...

Describe any alternatives/workarounds you're currently using

I managed to realize the injection by doing this :

import {ɵngrx_modules_effects_effects_e} from '@ngrx/effects';

imports: [
    EffectsModule.forFeature([...fromStore.effects]), //here i import my other effects
  ],
 providers: [
    {
      provide: TreeService,
      useClass: TestCaseWorkspaceService
    },
    {
      provide : ɵngrx_modules_effects_effects_e,
      useFactory : (actions$, service) => {
        return [new TreeNodeEffects(TEST_CASE_WORKSPACE_ROOT_URL, MAIN_TREE_ID, actions$, service)];
      },
      deps : [Actions, TreeService],
      multi : true
    }

Basically, i used the exported FEATURE_EFFECTS token, however the exported name 'ɵngrx_modules_effects_effects_e' suggest that it's not an official API, so i'm relectant to use it in my application...

This token is used in ngrx forFeature method in platform/modules/effects/src/effects_module.ts

@NgModule({})
export class EffectsModule {
  static forFeature(
    featureEffects: Type<any>[]
  ): ModuleWithProviders<EffectsFeatureModule> {
    return {
      ngModule: EffectsFeatureModule,
      providers: [
        featureEffects,
        {
          provide: FEATURE_EFFECTS,
          multi: true,
          deps: featureEffects,//<-- maybe we should be able to provide deps here ?
          useFactory: createSourceInstances,
        },
      ],
    };
}

Other information:

I'm sorry if i missed something, i'm new to angular/ngrx and i'm definitly not an expert with angular injection system. But it seems to me that ngrx should have an official way to provide explicit dependencies to effects...

Maybe it's just changing the exported name of the token and add some documentation ?

Thank you for your attention

@leon-marzahn
Copy link
Contributor

@j-thebault Hey, i know this is old for quite some time, but have you found a solution for this? Otherwise i would have to create another issue for this, because i need this :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants