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

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 212
  • Comments: 122 (27 by maintainers)

Most upvoted comments

If you want to use an entry component in MainComponent then you should provide it in AppModule

Ok, in this case I’m changing this issue into a feature request.

IMO these use cases should be handled by Angular itself rather than by moving things along the DOM manually.

So your solution indeed is to move everything into the main module?

IMO this totally breaks the module concept of Angular which should allow to group functionality blocks into one module.

This means basically that things like modals are impossible to use with a lazy load architecture.

Wow, so your opinion is that we should rather move DOM content, like Angular Material does. See here: https://github.com/angular/material2/blob/master/src/lib/core/portal/dom-portal-host.ts#L30-L55

If this is really the best practice to handle this in Angular, basically we can dump Angular and start using JQuery again.

Sorry, but I cannot take this approach seriously.

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.

This solves my issue as well.

In sum, all you need to know is that when you want to dynamically create a component that’s declared in a lazy module, you need to actually use ComponentFactoryResolver from a component that’s declared in that lazy module. The root injector (which contains the root ComponentFactoryResolver) will not know about any entryComponents declared in a loaded lazyModule.

Looks kinda weird, but this is how Angular is designed (which makes sense) but this actually creates extra complexity when working with the framework, imho.

How Angular team could leverage this: Whenever a route is activated, the root injector should append the entryComponents listed on that lazyModule automatically and whenever the route is changed, the previously appended entryComponents should be automatically destroyed, this would ensure less complexity and avoid over flooding the root injector with extra component factories.

I’ll submit a feature request for this.

Thank you!

You need to use an api similar to material’s https://material.angular.io/components/component/dialog Then it should work

Faced with same issue today - component for modal defined in lazy loaded module does not handled by app modal service (it cant find it despite entryComponents usage). Forced to move it to main bundle that breaks lazy modules structure and usage logic 😕

@gcorgnet - Sure. So my use case was, I have a common toolbar on every page of my app, but within the toolbar I wanted to add buttons and tools for additional functionality based on what page I was on. In order to achieve this I created a component to hold these buttons/tools and their logic and I wanted to keep these components inside of the module they are associated with. So, essentially nothing outside of my module knows anything about these specific toolbar functions while still being able to show them on the common toolbar. Below is my working solution which I hope will help you:

All I’m doing with the toolbar service is creating an observable, so your lazy component can pass it’s componentFactoryResolver and injector references to the toolbar common component that is listening for the receiveContext Event.

toolbar.service.ts

@Injectable()
export class ToolbarService {
    contextReceivedSource = new Subject<any>();
    contextReceived$ = this.contextReceivedSource.asObservable();

    receiveContext(componentFactoryResolver: ComponentFactoryResolver, injector: Injector) {
        this.contextReceivedSource.next({ resolver: componentFactoryResolver, injector: injector });
    }
}

In your lazy loaded component you’ll want to inject componentFactoryResolver and injector and fire an event in the toolbar service.

lazy loaded toolbar component

...
constructor(private componentFactoryResolver: ComponentFactoryResolver, private injector: Injector) {}
...
ngOnInit() {
  this.toolbarService.receiveContext(this.componentFactoryResolver, this.injector);
}
...

Finally, in my core toolbar component I’m subscribing to the observable in the toolbar service so that anytime an event is fired it will try to inject and create the lazy component that I need. It’s also important to destroy the componentRef that you create otherwise you will end up with memory leaks.

...
@ViewChild('toolbarTarget', {read: ViewContainerRef}) toolbarTarget: ViewContainerRef;
component: Type<Component>;
refInjector: ReflectiveInjector;
resolverSub: Subscription;
refInjector: ReflectiveInjector;
componentFactoryResolver: ComponentFactoryResolver;
injector: Injector;

ngOnInit() {
  this.resolverSub = this.toolbarService.contextReceived$.subscribe(resolver => {
      this.componentFactoryResolver = resolver.resolver;
      this.injector = resolver.injector;
    });
}

updateToolbar(data: any) {
    this.clearComponent();
    this.component = data['toolbar'];
    if (this.component) {
      const childComponent = this.componentFactoryResolver.resolveComponentFactory(this.component);
      this.refInjector = ReflectiveInjector
          .resolveAndCreate([{provide: this.component, useValue: this.component}], this.injector);
      this.componentRef = this.toolbarTarget.createComponent(childComponent, 0, this.refInjector);
    }
  }

  clearComponent() {
    this.toolbarTarget.clear();
    if (this.componentRef) { this.componentRef.destroy(); };
  }

  ngOnDestroy() {
    this.resolverSub.unsubscribe();
    this.clearComponent();
  }

Your dynamically created component will then be placed wherever you put the corresponding #toolbarTarget

<div #toolbarTarget></div>

As an aside, I’m using this line this.component = data['toolbar']; in the common toolbar component to get the lazy loaded component reference from the route. If you want to see the full code for this I can post that, but it’s outside the scope of this discussion.

{ path: '', component: yourComponent, data: { toolbar: yourToolbarComponentToInject } }

Let me know if you have any further questions!

@msarica pointed out to me today that if you create a service that is lazily loaded and have it extend your global service that opens popups, then use the lazily loaded service to open the popup, it will work as expected:

Global PopupService

@Injectable({ providedIn: 'root' })
export class PopupService {
  constructor(
    private injector: Injector,
    private overlay: Overlay,
  ) {}

  open<T = any>(component: ComponentType<T>) { ... }
}

Specific Service only lazily loaded in MyFeatureModule

@Injectable()
export class MyFeaturePopupService extends PopupService {}

Usage in a component that is part of the lazily loaded MyFeatureModule

@Component({ ... })
export class MyFeatureComponent {
  constructor(
    private myFeaturePopupService: MyFeaturePopupService,
  ) {}
  
  openPopup() {
    this.myFeaturePopupService.open(MyFeaturePopupComponent);
  }
}

Example definition of lazily loaded module

@NgModule({
  imports: [MyFeatureRoutingModule],
  declarations: [
    MyFeatureComponent,
    MyFeaturePopupComponent,
  ],
  entryComponents: [MyFeaturePopupComponent],
  providers: [MyFeaturePopupService],
})
export class MyFeatureModule {}

Tested in Angular 7.

Note: Our code leverages the Angular CDK’s Overlay, but the concept is the same (according to other parts of this thread, it’s the Injector that is of concern).

Same issue there … Impossible to use an entryComponents in a lazyLoaded module without breaking the lazy modules logic : My LazyLoaded module depends on an entryComponent declared in my AppModule 😦

Ok, if this is the intended behavior, how can specific tasks like the use cases above be accomplished?

I don’t think that blowing up the main module is a proper solution.

I don’t know what is the best approach for modals and lazy loading, but anyway in your plunkr it works as intended and there’s no angular bug here. For discussion about modals it’s better to use support channels such as gitter and stackoverflow

This issue is still not resolved?

It looks like that the issue does not exist in Angular 9 any more due to the ivy implementation (tested with 9.0.0-next.7). You can dynamically create a component of a lazy loaded module from outside of the lazy module. It appears to be the case that the entry component declaration is not needed any more for dynamic components in Ivy. Ivy does not need a separated component factory which used to be generated by the compiler. The component factory info is embedded in the component definition with Ivy(?). Once you have a component type, you should be able to get its component factory and then create an instance of it. That is just my impression. Take my word with a grain of salt

Ran into this same issue, I did come to a resolution though after looking through ng-bootstrap modal source code. Essentially the issue (from my understanding please correct me if I’m wrong) is that your lazy modules are not included in the initial injector when your app is bootstrapped and the initial injector cannot be modified once it is set. Which is why you get the error in the OP. When one of your lazy modules is loaded it gets its own injector with references to whatever you declare or provide in your lazy module. That being said, as long as wherever you create your dynamic component at has reference to the correct injector and componentFactoryResolver you can indeed reference an entryComponent outside of the lazy loaded module.

So, what I did was create a singleton service to store the injector and componentFactoryResolver of the dynamic component I want to create. This service needs to be outside of your lazy modules. Then whenever I go to dynamically create a component I can call this service to get what I need.

Code below will be wherever you are creating your dynamic component outside of your lazy module

@ViewChild('parent', {read: ViewContainerRef}) parent: ViewContainerRef;
  private componentRef: ComponentRef<any>;
...
const childComponent = this.componentFactoryResolver.resolveComponentFactory(yourComponentRef);
this.refInjector = ReflectiveInjector.resolveAndCreate([{provide: yourComponentRef, useValue: yourComponentRef}], this.injector);
this.componentRef = this.parent.createComponent(childComponent, 0, this.refInjector);
<div #parent></div>

Then in your parent component for your entryComponent you’ll inject injector and componentFactoryResolver and set their values in the shared service:

constructor(private componentFactoryResolver: ComponentFactoryResolver, private injector: Injector) {}

Let me know if this doesn’t make any sense and I can elaborate further. Edit I forgot to mention I’m using Angular 2.4.9.

I wanted to confirm that ivy seems to take care of this issue. I just stumbled on this issue today when I rewrote my modules to be lazy loaded which contained entry components and a shared services to instantiate them only to find a new error stating the component factory couldn’t be found. I was actually shocked to read this was an issue in the first place.

At any rate, I just enabled ivy in my existing angular 8.2 project and all seems to be working as expected.

@jmcclanahan I just solved the same issue before finding this post. One thing I noticed is if you want to save a few characters in your function declarations, you can get a reference to the ComponentFactoryResolver using the Injector that you pass. you can just do: injector.get(ComponentFactoryResolver);

And that should return the reference you need. But in the end it gives the same result as passing the ComponentFactoryResolver in as a parameter in the function as well.

Coping over from #17168 (closed as a duplicate of this one)

Current behavior If you have a singleton service that uses a ComponentFactoryResolver provided by the App’s RootInjector to dynamically create components and you wish to create an entryComponent declared in a lazy module, this will fail because the root injector does not know about it.

Expected behavior This is actually the expect behavior considering that the root injector will not know about entryComponents known by the child injector.

What is the motivation / use case for changing the behavior? The motivation is to leverage the complexity to create dynamic components though the modular design of Angular is correct.

Angular version: 2.4.9

Proposed solution: Even though this goes against the modular design adopted by Angular itself, I think that the complexity provided to create dynamic components could be softened by simply appending the LazyModule’s entryComponents to the RootInjector’s entryComponents and to avoid flooding the RootInjector, whenever you navigate out (which destroys the LazyModule), the previously injected entryComponents would be erased from the array.

Simply talking:

Page is loaded -> RootInjector is created. Issues a navigation which activates a LazyModule -> ChildInjector is created. RootInjector.entryComponents.append(childInjector.entryComponents) Issues a navigation to somewhere else -> LazyModule is no longer necessary, thus destroyed. RootInjector.entryComponents.destroyLastAppendedEntryComponents() Hope I could suggest something good.

In the beginning, there was nothing, 'Let’s create a view! ', says jQuery team, 'Let’s have a list! ', says Angular team.

Building on @CWSpear’ s solution, I got this working by simply adding my existing PopupService to the providers array of the component. So I didn’t need to create a separate “feature-specific” PopupService.

So like so:

@Component({
  ...
  providers: [PopupService]  //<---- generic PopupService
})
export class MedicationPortletComponent implements OnInit, OnDestroy {
...

Alternatively, you can also add the PopupService to the providers array of the lazy-loaded module’s NgModule. Eg:

@NgModule({
  declarations: [
    ...
  ],
  imports: [
    ...
  ],
  providers: [PopupService] //<--- here's the PopupService!
})
export class SharedFeaturePatientModule {}

Just put your entry components into their own submodule and import that into the app and nowhere else.

Even if it did work, it does not address the REAL problem. the problem is if I add a component to the entryComponents of an NgModule, and that module is imported into a lazily loaded module in my app, then the entryComponents should automatically get registered with the apps entry components. There should be no further work required. I would further say that any component in the entryComponents of any NgModule should automatically wind up in the entryComponents of the app module. This is currently not the case. If it were then we wouldn’t be here.

@pixelbits-mk That would make all the dynamic components (like modal and the like) eager loaded, but the point here is make them being able to be lazy loaded to not slow down the initial load of the app (especially as the project grows), just like the components that call them.

Let’s say that a lazy loaded ComponentA calls dynamically a lazy loaded dynamic ComponentB. If ComponentA knows that it will call ComponentB you can just import ComponentBModule in ComponentAModule. This is not the ideal case, but I can live with it.

The main problem arises (in my opinion) when ComponentA doesn’t know that ComponentB will be loaded. For example, if ComponentB is a modal and ComponentA calls a method showModal() in a service, and the service loads ComponentB dynamically behind the scenes, ComponentA wouldn’t know that.

What I do now is including the ComponentB reference as a parameter in the method, like showModal(ComponentB), in such a way that ComponentA now knows that the ComponentB will be loaded, but that’s bad in my opinion (each call to the method must pass the component reference).

If Entry Components were available without having to import their modules explicitly (what I think this issue is about), that would solve it (maybe Angular could have a way to detect that ComponentA calls a service that imports ComponentB and make ComponentAModule import implicitly ComponentBModule, and although it could have the undesirable effect of also importing modules of components whose references are imported but the reason of the import is not to create them dynamically, I would see this more as an edge case, and would be okay with it).

I haven’t tested (yet) @jonrimmer suggestion, but that seems promising.

I spent a couple of days breaking apart my companies project and implementing lazy loading. It wasn’t until the end that I realized our modals weren’t working due to being entries in their respective modules. We’ve reverted back and are waiting on a fix…

Is this something that’s scheduled or should we explore a workaround. As people are doing above.

I believe that this is fixed in Angular v9 running ivy. If anyone still faces similar problems, please open a new issue with a minimal reproduce scenario. Thnx!

My issue was caused because I used @Injectable({providedIn: 'root'}). Changing it to @Injectable({providedIn: MyModule}) solved it. 😄

This makes sense, because the service needs access to the lazy-loaded modules entry components. When provided in the root, it cannot access them because the module is temporarily disconnected from the root injector.

I got this working in Angular 8.3.6. I have a library module with entry components (mat dialogs) that won’t load if I add them to the library modules entry components. It says can’t find component factory for MyCustomDialog in the console log when I tried to open it.

Solution is to create a static method in the library module’s NgModule class that returns an array of all the module’s entry components. Then call this method from the app modules NgModule.

@NgModule({
    declarations: [
        MyCustomDialogComponent
    ],
    imports: [
        CommonModule
    ],
    exports: [
        MyCustomDialogComponent
    ]
	// no need to add the dialog component to entryComponents here.
})
export class MyCustomModule {
    static getEntryComponents() {
        const entryComponents = [];
        entryComponents.push(MyCustomDialogComponent);
        return entryComponents;
    }
}

import {MyCustomModule} from 'my-custom-library'; // import library from node_modules

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule,
        AppRoutingModule,
        BrowserAnimationsModule,
        MyCustomModule
    ],
    providers: [],
    bootstrap: [AppComponent],
    entryComponents: [].concat(MyCustomModule.getEntryComponents())
})
export class AppModule {
}

I know this still doesn’t fix the entryComponents in the library not working but at least with the static method the app module doesn’t have to know about the entry components in the custom library. It just calls that method and gets whatever is listed in the library. There’s no responsibility on the app to know what components in the library are entry components.

All you need to do is create a separate widgets module that declares all your dynamic components and also includes them as entryComponents. Then import this module from AppModule. This will ensure that your entry components are registered with the root injector.

This solution is clean and doesn’t break Lazy encapsulation.

@NgModule({
  declarations: [
    ModalComponent,
    ... more dynamic components ...
  ],
  entryComponents: [
     ModalComponent,
    ... more dynamic components ...
  ]
})
export class DynamicModule {

}

AppModule:

@NgModule({
   declarations: [
      AppComponent
   ],
   imports: [
      BrowserModule,
      AppRoutingModule,
      BrowserAnimationsModule,
      DynamicModule
   ],
   providers: [],
   bootstrap: [
      AppComponent
   ]
})
export class AppModule { }

In the issue #23819 I asked about making the entry components behave in a similar way as the services with providesIn: 'root'. Closed that issue because it seems both issues are intended to solve the same thing. I hope this issue will be solved soon because this is an important feature 😃

Update

From what I see in the non-minified code, when providesIn is defined in the service, it register the factory so that it can already be used (without the need of importing it in a module), if I understood correctly:

var Injectable = makeDecorator('Injectable', undefined, undefined, undefined, function (injectableType, options) {
    if (options && options.providedIn !== undefined &&
        injectableType.ngInjectableDef === undefined) {
        injectableType.ngInjectableDef = defineInjectable({
            providedIn: options.providedIn,
            factory: convertInjectableProviderToFactory(injectableType, options)
        });
    }
});

I assume there is a way to apply a similar logic in a component with some option like @Component({ ... entryComponent: true }) so that when the chunk that contains it is loaded, the factory is defined in the resolver (there should be a module that includes the component in entryComponents with the component dependencies, otherwise it would cause a compile time error).

@werts et al: Can I recommend you take this support thread to another channel? StackOverflow or Gitter might be more suitable. As it is, I am subscribed to this issue (as I am sure are many others) and it is generating a lot of noise right now which is getting a little off-topic.

On the plus side: great to see such a helpful community!

Just to add to this. My use case is that I have created a ModalManagerService in my AppModule which has an open method that all other parts of the app call to open a modal. It gets passed a component which is then opened as a modal. I also have a closeAll method which is used when the modals need to be closed by some action other than the user closing them e.g. route change due to session timeout.

@Dunos - Maybe an example will be best. Say I’m navigating from the index page of my app to Page A. You will have a corresponding route for Page A, that will define Page A’s module/component. Page A will also have a separate component defined that I want to display in the global toolbar. So, inside Page A’s main component you will inject ComponentFactoryResolver and Injector and then fire a receiveContext event. This bit of code:

constructor(private componentFactoryResolver: ComponentFactoryResolver, private injector: Injector) {}
...
ngOnInit() {
  this.toolbarService.receiveContext(this.componentFactoryResolver, this.injector);
}

Sorry, I could see how that could be confusing. You don’t put that code in the component you want to display in the toolbar, but rather the component associated to the page you are on.

I publish a package for this issues. some code copy from jonrimmer. It looks like that the issue does not exist in Angular 9. If you need fix this now. you can use @aiao/lazy-component sample code here https://github.com/aiao-io/aiao/tree/master/integration/lazy-component

@mlc-mlapis I think that the limitation in angular that many would like to overcome is that entry components can only be instantiated and placed in the dom by the app. The app does not need to know about a dialog box that a module that I import into a lazy loaded module uses. The current concept of entry components breaks the modular pattern of angular.

Wow. This was very unexpected.

I implemented my own dialog system based on @angular/cdk portals and overlays: https://stackblitz.com/edit/cdk-dialog-example-p1. Got this issue as well.

The workaround mentioned by @CWSpear works: I had to extend the service in my feature module and that worked for me. How weird!

Is there a more elegant solution for this?

… the general supported solution should be available (some new APIs + support in Ivy) … due to Jason’s presentation http://www.youtube.com/watch?v=2wMQTxtpvoY&t=131m24s … in Angular 7.2 … but I am not sure if the version 7.2 was mentioned correctly.

What I seriously don’t understand is this god damn router. Check this plunker (forked from @patkoeller 's example) http://plnkr.co/edit/keMuCdU9BwBDNcaMUAEU?p=preview @ src/page1.ts

What I basically want to do is inject some component into the toplevel app and use [routerLink] directive with commands relative to its defining lazy loaded module like: [routerLink]="['./', 'sub', 'component'] to generate /page-1/sub/component. If I pass an injector to createComponent with some ActivatedRoute and it works for my case it screws up every other routerLink, but if I reassign router.routerState.snapshot to the state from the resolve and pass the injector with this router instance it seams to work as intended… very confusing!

Should I file a bug?

@crysislinux ngComponentOutlet is great but it does not allow us to pass data to the component yet so it’s not a solution.

@werts,

All you need to understand is whenever you navigate to a lazy loaded route, the activated route will spawn a child injector which contains the entryComponents for that lazyModule. If you have a global modalService defined in the AppModule (which is the application’s root injector), the componentFactoryResolver will not know any new entryComponents from any lazyModule. So, one of the ways to solve this issue is to get the instance of complementFactoryResolver from a lazyModule’s component and somehow tell the modalService “hey, use this injector/componentFactoryResolver to render the wanted entryComponent”.

Seems a bit hard to understand but it’s not.

@rraya I have submitted a feature request regarding this “issue” (it’s not really an issue if you think about it), please see #17168.

Thanks @jmcclanahan. Are you able to tell us a bit more about what that service looks like and how it is set up? I am struggling with a similar issue, trying ti dynamically load a component from one lazy loaded module into a component from another lazy-loaded module and even though (I think) I have added the entry components in the right place, I get told I haven’t. Thanks

@Airblader You are right, we know. It was just a small reminiscence back to history. 😄

AFAIK with Ivy entryComponents will no longer be necessary, right? Since components will have locality so just dynamically importing them will always work?

@asmith2306 why do you not use spread operator? it looks ugly

Because it doesn’t work with it. There’s a bug about it somewhere.

Confirmed this is not resolved in Angular 8.2.0 yet. Since the OP had been created 2.5 years ago, the landscape of Angular had changed a lot, and Angular Material 2 had become Angular Components.

As indicated by the other commentators, Angular Material uses DOM so application developers do not have to use DOM when loading an application component in MatDialog, even if the application component is declared in the entryComponents of the sub module lazily loaded.

However, doing the same DOM things in a business application is looking odd, against Angular’s application programming guidelines.

It will be nice that the feature request of the OP could be implemented so ComponentFactoryResolver could “see” an entry component declared in a sub module lazily loaded, one way or the other. Declaring an entry component of a lazy module in app.module is working, but ugly.

In addition to the dirty working solutions as mentioned above: 1. DOM, 2. Declaring the component in app.module, I would provide another solution, less dirty, below.

@jonrimmer This is minimal intrusive and works perfectly for our use case. A giant thanks from me and my team 😃

@jonrimmer best solution

@ravtakhar you probably want to look at the workaround as this is in the Backlog and doesn’t have a priority assigned at this time.

Any updates on this?

Our custom solution involves constructor-injecting the ComponentFactoryResolver and Injector into each component that could open our global sidebar. The calling component then passes those references (its own) to a service along with the desired Component. The service uses those instances to create the component. Over-complicated and over-verbose.

@jmcclanahan we got ngComponentOutlet now, it makes things much simpler.

<ng-container  *ngComponentOutlet="yourComponentClass;injector: yourInjector;"></ng-container>

@jmcclanahan Ah perfect, many thanks!!! Got it working now 😃