I can use <tamplete> syntax and a entry component as a container to create a dynamic component. Notice it will create a empty div as a placeholder in the DOM. If we don't wanner this empty div, we can actually using ng-conainer together with ngTemplateOutlet (for template ref) and ngTemplateOutletContext (the context).
import { Component, TemplateRef, ComponentRef, ViewContainerRef, ViewChild, AfterContentInit, ComponentFactoryResolver } from '@angular/core';
import { AuthFormComponent } from './auth-form/auth-form.component';
import { User } from './auth-form/auth-form.interface';
@Component({
selector: 'app-root',
template: `
<div>
<div #entry></div>
<template #tmpl let-obj let-location="location">
<details>
<summary>{{obj.name}}</summary>
<p> - Age: {{obj.age}}</p>
<p> - Address :{{location}}</p>
</details>
</template>
<hr />
<ng-container
[ngTemplateOutlet]="tmpl"
[ngTemplateOutletContext]="ctx"
></ng-container>
</div>
`
})
export class AppComponent implements AfterContentInit {
@ViewChild('entry', { read: ViewContainerRef }) entry: ViewContainerRef;
@ViewChild('tmpl') tmpl: TemplateRef<any>;
ctx = {
$implicit: {
name: 'John',
age: 34
},
location: 'USA'
}
ngAfterContentInit() {
this.entry.createEmbeddedView(this.tmpl, {
$implicit: {
name: 'Zhentian',
age: 27
},
location: 'China'
})
}
}

And in the generated DOM we can see that there is no empty div created.