0

I have a service like this

@Injectable()
export class MyService {
  constructor(private store: Store, @Optional() type: string){}

  static forType(type: string) {
    return { provide: MyService, deps: [Store], useFactory: factoryFn.bind(type) }  
  }

}

export function factoryFn(store: Store, type: string) {
  return new MyService(store, type);
}

and want to inject it into my component like this

@Component{ 
  providers: [MyService.forType('hello')]
}
export class MyComponent {}

but this gives me following error

Function calls are not supported in decorators but 'factoryFn' was called in 'MyService'
'MyService' calls 'factoryFn'.

The reason that I want to have it as a static method on the actual service is, because I don't want the component to know which dependencies MyService needs. MyService is also used at many different places, so with this way, I also avoid duplications.

Is there a way to trick Angular into allowing the function call?

Best regards, Benedikt

Jeff Mercado
  • 129,526
  • 32
  • 251
  • 272
Bene
  • 874
  • 1
  • 10
  • 15

1 Answers1

0

After some search, I found a neat workaround on how this can be done. We can create a token based on our parameter that we want and then use this token in the Service. To automatically inject both the service and its token, we can leverage the fact, that Angular flattens out the providers array, so we can just return an array with both.

export const MY_TOKEN = new InjectionToken<string>('MY_TOKEN');
@Injectable()
export class MyService {
  constructor(private store: Store, @Inject(MY_TOKEN) type: string){}

  static forType(type: string) {
    return [{ provide: MY_TOKEN, useValue: type}, MyService]
  }
}

So then we end up with this syntax for using the service and everything works, also in AOT:

@Component{ 
  providers: [MyService.forType('hello')]
}
export class MyComponent {}
Bene
  • 874
  • 1
  • 10
  • 15