Base image by Peggy und Marco Lachmann-Anke from Pixabay
How can you inject a dynamic, lazy-loaded component into a Material Dialog at runtime?
First, let me say that this might be overkill in many cases. Basic OO can often solve this kind of problem. But if you need to lazy-load a component at runtime and show that component in a mat-dialog then this will be of use. Thanks to Jason Warner for pointing me in the right direction!
This example will walk you through a basic scenario of showing a dialog with some common content as well as showing content injected from outside the dialog. An example of this kind of scenario might be a dialog that shows the details of an object if there is only one object to show, and shows an additional navigation header if more than one object is shown so the items can be iterated by the user.
We cannot use content projection because the dialog is not in any parent component’s template. The dialog is created dynamically at runtime in the DOM. To inject the component we’ll have to pass it as data to the dialog.
Here is the entire solution on StackBlitz.
We will start at the point where we have the app.component injectingDynamicDialogService, which has one method, showDialog.
First, we create two standalone components that will be injected into the dialog conditionally. We’ve called them injected-alpha and injected-beta, and you can easily see where the changes for beta need to be:
It’s the parent component that, based on application logic, will decide which component the dialog will instantiate. The business logic in the example is a button for Alpha and a button for Beta. Both buttons will call the same method to launch the same dialog, but will pass in an Observable that the dialog can use to instantiate the component when needed.
Lazy-loading a component will return a promise, so we will transform that into an Observable:
When one of the buttons is clicked we pass the corresponding Observable to the service’s showDialog method:
The showDialog method in the service opens the dialog, passing the argument as the data property in the dialog config.
The component is not instantiated yet. Something has to subscribe to the Observable to cause the lazy load to happen. We do this with the async pipe in the template of the dialog. The trick to getting angular to use the value in the Observable as a component to render to the page is to add the *ngComponentOutlet binding on the container, setting it to the Observable.
That’s a working example of showing a lazy-loaded, dynamic component in a Material Dialog!
The code is straightforward as long as your use case is simple. But, what if the injected component needs configuration, services, or to emit events that the dialog needs to respond to? Stay tuned for my next article!
Angular Dynamic Component in Material Dialog was originally published in ngconf on Medium, where people are continuing the conversation by highlighting and responding to this story.