Useful or not, from you.
angular Entry Components of a Lazy Loaded NgModule are not available outside the Module

I'm submitting a ... (check one with "x")

[ ] bug report => search github for a similar issue or PR before submitting
[X] feature request
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Follow-up issue for #12275 as requested by @DzmitryShylovich

Current behavior entryComponents of a lazy loaded NgModule cannot be rendered using ComponentFactoryResolver. Error message: No component factory found for {{entryComponent}}

Expected behavior entryComponents should be available just like if the module is imported

Minimal reproduction of the problem with instructions http://plnkr.co/edit/9euisYeSNbEFrfzOhhzf?p=preview

I created a simple setup, similar to what we use internally. Main component provides a method to render a Type. EntryComponent is declared as entryComponent in Page1Module. However after having loaded Page1Module, when trying to render EntryComponent via ComponentFactoryResolver, No component factory found for EntryComponent is thrown.

What is the motivation / use case for changing the behavior? Render entryComponents of child modules at root level. Use cases for this approach are

  • Modals that shall be rendered on top of everything
  • Notifications
  • etc.

Please tell us about your environment: We're using currently Angular 2.1.1 but this affects the latest version of Angular (2.4.6) as well (see plnkr).

  • Language: TypeScript ^2.0.0
That's a useful answer
Without any help

I don't think any workaround is viable if it requires the code you're integrating with to know about it, because there's plenty of 3rd party code that just uses ComponentFactoryResolver without knowing about your special alternative registry.

With that in mind, here's my "solution": CoalescingComponentFactoryResolver. This is a service that should be provided by the app module and initialised in its constructor, like so:

@NgModule({
 providers: [CoalescingComponentFactoryResolver]
})
class AppModule {
  constructor(coalescingResolver: CoalescingComponentFactoryResolver) {
    coalescingResolver.init();
  }
}

Then, lazy-loaded modules should inject it and register their own ComponentFactoryResolver instances with it. Like so:

@NgModule({})
export class LazyModule {
  constructor(
    coalescingResolver: CoalescingComponentFactoryResolver,
    localResolver: ComponentFactoryResolver
  ) {
    coalescingResolver.registerResolver(localResolver);
  }
}

When this is done, entry components in the lazy-loaded module should be available from non-lazy loaded services.

How it works: When initialised, it injects the root app's ComponentFactoryResolver and monkey patches the resolveComponentFactory method to call its own implementation. This implementation first tries resolving the component factory on all the registered lazy-module resolvers, then falls back to the root app resolver (there's a bit of extra logic to avoid cyclic calls, but that's the gist).

So, yeah, a pretty gross hack. But it works, right now, in Angular 7. Maybe it will be of use to someone.