Reputation: 209
I would dynamically component to another component in the service , Firstly inside the service factory both components and I created the component with access to ViewContainer. But the component cannot be create !
Service :
@Injectable({
providedIn: 'root'
})
export class ModalService {
componentRef: ComponentRef<ModalTemplateComponent>;
constructor(private _modalService: BsModalService,
private resolver: ComponentFactoryResolver,
private injector: Injector) {
}
open(componentType: any) {
const contentFactory = this.resolver
.resolveComponentFactory(componentType);
const templateFactory = this.resolver
.resolveComponentFactory(ModalTemplateComponent);
const componentRef = templateFactory.create(this.injector);
componentRef.instance.container.createComponent(contentFactory);
this._modalService.show(componentRef.componentType, {class: 'modal-lg', initialState: {data: {test:true}});
}
}
Component :
selector: 'lib-modal-template',
template: `
<h1>{{title}}</h1>
<ng-container #container>
</ng-container>
`,
styleUrls: ['./modal-template.component.css']
})
export class ModalTemplateComponent implements OnInit {
title:string;
@ViewChild('container', {read: ViewContainerRef, static: true}) container: ViewContainerRef;
}
example :
this._modalService.open(NewUserForm,...);
Upvotes: 6
Views: 2676
Reputation: 12596
First, this line will create new instance of ModalTemplateComponent
, instead of componentRef
, so you are not working on same instance.
this._modalService.show(componentRef.componentType, {class: 'modal-lg', initialState: {data: {test:true}}});
I made some adjustment (using ngComponentOutlet
), it will work as you expected:
ModalService
@Injectable({
providedIn: 'root'
})
export class ModalService {
constructor(private _modalService: BsModalService,
private resolver: ComponentFactoryResolver,
private injector: Injector) {
}
open(componentType: any) {
const ref = this._modalService.show(ModalTemplateComponent, {class: 'modal-lg', initialState: {data: {test:true}}});
(ref.content as ModalTemplateComponent).componentType = componentType;
}
}
ModalTemplateComponent
@Component({
selector: 'app-modal-template',
template: `
<h1>{{title}}</h1>
<ng-container *ngComponentOutlet="componentType">
</ng-container>
`,
styleUrls: ['./modal-template.component.css']
})
export class ModalTemplateComponent implements OnInit {
title: string = 'modal-template';
@Input() componentType: any;
constructor() { }
ngOnInit() {
}
}
Online demo: https://stackblitz.com/edit/angular-1srnej?file=src%2Fapp%2Fmodal.service.ts
===============================
if you want to working with dynamic component instance, we can using following solution:
ModalTemplateComponent
@Component({
selector: 'app-modal-template',
template: `
<h1>{{title}}</h1>
<ng-container #container>
</ng-container>
`,
styleUrls: ['./modal-template.component.css']
})
export class ModalTemplateComponent implements OnInit, OnDestroy {
title: string = 'modal-template';
component: any;
componentRef: ComponentRef<any>;
@Input() set componentType(c: any) {
this.component = c;
this.renderContent();
}
@ViewChild('container', {
read: ViewContainerRef,
static: true
}) container: ViewContainerRef;
constructor() { }
ngOnInit() {
}
renderContent() {
this.container.clear();
const injector = this.container.injector;
const cfr = injector.get(ComponentFactoryResolver);
const componentFactory = cfr.resolveComponentFactory(this.component);
const componentRef = this.container.createComponent<any>(componentFactory);
componentRef.instance.content = 'content from ' + this.title;
this.componentRef = componentRef;
}
ngOnDestroy() {
if (this.componentRef) {
this.componentRef.destroy();
}
}
}
AlertContentComponent
export class AlertContentComponent implements OnInit {
@Input() content = '';
constructor() { }
ngOnInit() {
}
}
Upvotes: 3