2

I have multiple modules, each containing various components, and a parent component that needs to contain one of these components.

Since I cannot use routes to achieve this, I authored a service that given a moduleName :string and a compomnentName : string returns the corresponding component class.

See ComponentDirectoryService in this stackblitz.

I am imitating how the router module allows feature modules to inject their own routes:

  • ComponentDirectoryModule has a forRoot and forChild methods to which a DIRECTORY_ENTRIES value is passed
  • each feature module (p1 and p2 in stackblitz) calls forChild to provide its DIRECTORY_ENTRIES
  • AppModule calls forRoot which provides ComponentDirectoryService passing in the cumulated (calls to forChild) value of DIRECTORY_ENTRIES

Everything works fine in dev mode.

In production mode everything works, but I get this scary warning:

Can't resolve all parameters for ComponentDirectoryService in ...component-directory.service.ts: (?). This will become an error in Angular v6.x

What puzzles me is that the only parameter to the service are the directory entries...

EDIT 1

Like Angular declares the ROUTES injection token:

export const ROUTES = new InjectionToken<Route[][]>('ROUTES');

so do I for DIRECTORY_ENTRIES:

export const DIRECTORY_ENTRIES = new InjectionToken<ComponentDirectoryEntry[][]>('DIRECTORY_ENTRIES');

Cec
  • 1,726
  • 3
  • 18
  • 31
  • looks like it happens because you use an array as an injection object and it could be the reason of the problem because AoT tries to find the class responsible for that token and it fails. It might be worth trying to use an explicit [injection token](https://angular.io/guide/dependency-injection#injectiontoken) instead – smnbbrv Apr 05 '18 at 09:47
  • Hello, I'm not sure I get what do you mean by explicit injection token ; I updated the question with how I declare the token and how router does – Cec Apr 05 '18 at 10:24
  • 1
    I mean try to use `Inject()` in the constructor: `constructor(@Inject(DIRECTORY_ENTRIES) private entries: ComponentDirectoryEntry[]) { }` – smnbbrv Apr 05 '18 at 11:39

1 Answers1

1

The compiler misses the information about what should be actually injected into your service.

That's why you need to explicitly use @Inject(<YOUR_INJECTION_TOKEN>) decorator to point that out:

constructor(@Inject(DIRECTORY_ENTRIES) private entries: ComponentDirectoryEntry[]) { }

This will internally set the metadata flag to the property entries and using this metadata Angular will know that DIRECTORY_ENTRIES should be injected here.

smnbbrv
  • 23,502
  • 9
  • 78
  • 109