如何动态地将组件添加到服务中的另一个组件
How to dynamically add component to another component in service
我会动态地组件到服务中的另一个组件,首先在服务工厂内部,这两个组件和我创建了可以访问 ViewContainer 的组件。但是无法创建组件!
服务:
@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}});
}
}
组件:
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;
}
示例:
this._modalService.open(NewUserForm,...);
首先,此行将创建 ModalTemplateComponent
的新实例,而不是 componentRef
,因此您不是在同一个实例上工作。
this._modalService.show(componentRef.componentType, {class: 'modal-lg', initialState: {data: {test:true}}});
我做了一些调整(使用 ngComponentOutlet
),它会如您所愿地工作:
模态服务
@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() {
}
}
在线演示:https://stackblitz.com/edit/angular-1srnej?file=src%2Fapp%2Fmodal.service.ts
=================================
如果你想使用动态组件实例,我们可以使用以下解决方案:
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() {
}
}
我会动态地组件到服务中的另一个组件,首先在服务工厂内部,这两个组件和我创建了可以访问 ViewContainer 的组件。但是无法创建组件!
服务:
@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}});
}
}
组件:
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;
}
示例:
this._modalService.open(NewUserForm,...);
首先,此行将创建 ModalTemplateComponent
的新实例,而不是 componentRef
,因此您不是在同一个实例上工作。
this._modalService.show(componentRef.componentType, {class: 'modal-lg', initialState: {data: {test:true}}});
我做了一些调整(使用 ngComponentOutlet
),它会如您所愿地工作:
模态服务
@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() {
}
}
在线演示:https://stackblitz.com/edit/angular-1srnej?file=src%2Fapp%2Fmodal.service.ts
=================================
如果你想使用动态组件实例,我们可以使用以下解决方案:
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() {
}
}