在 angular 中动态添加 Component 2/4
Dynamically add Component in angular 2/4
如何动态添加组件?
toolbar.component.ts:
@Component({
selector: 'app-toolbar',
template: '<button>Add Text component</button>'
})
export class ToolbarComponent {
constructor() { }
}
section.component.ts:
@Component({
selector: 'div[app-type=section]',
template: ''
})
export class SectionComponent {
constructor() { }
}
text.component.ts:
@Component({
selector: 'app-text',
template: '<p>This is dynamically component</p>'
})
export class TextComponent {
constructor() { }
}
view.component.ts:
@Component({
selector: 'app-view',
template: `<div class="container">
<app-toolbar></app-toolbar>
<div app-type="section" id="SECTION1" class="active"></div>
<div app-type="section" id="SECTION2"></div>
</div>`
})
export class SectionComponent {}
当我点击 ToolBarComponent 时,我想将 TextComponent 添加到具有 "active" class.
的 SectionComponent
我会用 ngFor 来做
view.component.ts:
@Component({
selector: 'app-view',
template: `
<div class="container">
<app-toolbar (addEvent)="addEvent($event)"></app-toolbar>
<div app-type="section" id="SECTION1" class="active">
<app-text *ngFor="let appText in textArray"></app-text>
</div>
<div app-type="section" id="SECTION2"></div>
</div>
`
})
export class SectionComponent {
public textArray: string[] = [];
public addEvent(event: string) : void {
textArray.push(event);
}
....
}
toolbar.component.ts:
import { Component, EventEmitter, Output } from '@angular/core';
@Component({
selector: 'app-toolbar',
template: '<button (click)="addNewText()">Add Text component</button>'
})
export class ToolbarComponent {
@Output addEvent: EventEmitter<string> = new EventEmitter();
constructor() { }
addNewText(): void {
this.addEvent.emit("");
}
....
}
在 section.component.ts 上公开 viewContainerRef
:
@Component({
selector: 'div[app-type=section]',
template: ''
})
export class SectionComponent {
@Input() active: boolean;
constructor(public viewContainerRef: ViewContainerRef) { }
}
将输出添加到 toolbar.component.ts:
@Component({
selector: 'app-toolbar',
template: '<button (click)="addComponentClick.emit()">Add Text component</button>'
})
export class ToolbarComponent {
@Output() addComponentClick = new EventEmitter();
constructor() { }
}
在 view.component.ts 中为 TextComponents 创建一个 ComponentFactory
以将它们动态添加到 active SectionComponents:
import { Component, AfterViewInit, ViewChildren, QueryList, ElementRef, ComponentFactoryResolver, ComponentFactory, OnInit } from '@angular/core';
import { TextComponent } from './text.component';
import { SectionComponent } from './section.component';
@Component({
selector: 'app-view',
template: `<div class="container">
<app-toolbar (addComponentClick)="onAddComponentClick()"></app-toolbar>
<div app-type="section" id="SECTION1" [active]="true"></div>
<div app-type="section" id="SECTION2"></div>
</div>`
})
export class ViewComponent implements AfterViewInit, OnInit {
@ViewChildren(SectionComponent) sections: QueryList<SectionComponent>;
activeSections: SectionComponent[];
textComponentFactory: ComponentFactory<TextComponent>;
constructor(private componentFactoryResolver: ComponentFactoryResolver) { }
ngOnInit() {
this.textComponentFactory = this.componentFactoryResolver.resolveComponentFactory(TextComponent);
}
ngAfterViewInit() {
this.activeSections = this.sections.reduce((result, section, index) => {
if(section.active) {
result.push(section);
}
return result;
}, []);
}
onAddComponentClick() {
this.activeSections.forEach((section) => {
section.viewContainerRef.createComponent(this.textComponentFactory);
});
}
}
我还有一个办法,请查收你的情况
html
<ng-container *ngComponentOutlet="COMPONENT"></ng-container>
.ts
import { COMPONENT } from './..dir../component'
或
html
<ng-container *ngComponentOutlet="option.component"></ng-container>
.ts
import { COMPONENT } from './..dir../component'
option = {
component: COMPONENT
}
或者如果它是动态的,将组件添加到 entryComponent
app.module.ts
import { COMPONENT } from './..dir../component'
@NgModule({
declarations: [COMPONENT],
/.
..
..
./
entryComponents: [COMPONENT]
});
html
<ng-container *ngComponentOutlet="option.component"></ng-container>
.ts
/** The COMPONENT is not imported since it is added to entrycomponent**/
@Input() option;
如何动态添加组件?
toolbar.component.ts:
@Component({
selector: 'app-toolbar',
template: '<button>Add Text component</button>'
})
export class ToolbarComponent {
constructor() { }
}
section.component.ts:
@Component({
selector: 'div[app-type=section]',
template: ''
})
export class SectionComponent {
constructor() { }
}
text.component.ts:
@Component({
selector: 'app-text',
template: '<p>This is dynamically component</p>'
})
export class TextComponent {
constructor() { }
}
view.component.ts:
@Component({
selector: 'app-view',
template: `<div class="container">
<app-toolbar></app-toolbar>
<div app-type="section" id="SECTION1" class="active"></div>
<div app-type="section" id="SECTION2"></div>
</div>`
})
export class SectionComponent {}
当我点击 ToolBarComponent 时,我想将 TextComponent 添加到具有 "active" class.
的 SectionComponent我会用 ngFor 来做 view.component.ts:
@Component({
selector: 'app-view',
template: `
<div class="container">
<app-toolbar (addEvent)="addEvent($event)"></app-toolbar>
<div app-type="section" id="SECTION1" class="active">
<app-text *ngFor="let appText in textArray"></app-text>
</div>
<div app-type="section" id="SECTION2"></div>
</div>
`
})
export class SectionComponent {
public textArray: string[] = [];
public addEvent(event: string) : void {
textArray.push(event);
}
....
}
toolbar.component.ts:
import { Component, EventEmitter, Output } from '@angular/core';
@Component({
selector: 'app-toolbar',
template: '<button (click)="addNewText()">Add Text component</button>'
})
export class ToolbarComponent {
@Output addEvent: EventEmitter<string> = new EventEmitter();
constructor() { }
addNewText(): void {
this.addEvent.emit("");
}
....
}
在 section.component.ts 上公开 viewContainerRef
:
@Component({
selector: 'div[app-type=section]',
template: ''
})
export class SectionComponent {
@Input() active: boolean;
constructor(public viewContainerRef: ViewContainerRef) { }
}
将输出添加到 toolbar.component.ts:
@Component({
selector: 'app-toolbar',
template: '<button (click)="addComponentClick.emit()">Add Text component</button>'
})
export class ToolbarComponent {
@Output() addComponentClick = new EventEmitter();
constructor() { }
}
在 view.component.ts 中为 TextComponents 创建一个 ComponentFactory
以将它们动态添加到 active SectionComponents:
import { Component, AfterViewInit, ViewChildren, QueryList, ElementRef, ComponentFactoryResolver, ComponentFactory, OnInit } from '@angular/core';
import { TextComponent } from './text.component';
import { SectionComponent } from './section.component';
@Component({
selector: 'app-view',
template: `<div class="container">
<app-toolbar (addComponentClick)="onAddComponentClick()"></app-toolbar>
<div app-type="section" id="SECTION1" [active]="true"></div>
<div app-type="section" id="SECTION2"></div>
</div>`
})
export class ViewComponent implements AfterViewInit, OnInit {
@ViewChildren(SectionComponent) sections: QueryList<SectionComponent>;
activeSections: SectionComponent[];
textComponentFactory: ComponentFactory<TextComponent>;
constructor(private componentFactoryResolver: ComponentFactoryResolver) { }
ngOnInit() {
this.textComponentFactory = this.componentFactoryResolver.resolveComponentFactory(TextComponent);
}
ngAfterViewInit() {
this.activeSections = this.sections.reduce((result, section, index) => {
if(section.active) {
result.push(section);
}
return result;
}, []);
}
onAddComponentClick() {
this.activeSections.forEach((section) => {
section.viewContainerRef.createComponent(this.textComponentFactory);
});
}
}
我还有一个办法,请查收你的情况
html
<ng-container *ngComponentOutlet="COMPONENT"></ng-container>
.ts
import { COMPONENT } from './..dir../component'
或
html
<ng-container *ngComponentOutlet="option.component"></ng-container>
.ts
import { COMPONENT } from './..dir../component'
option = {
component: COMPONENT
}
或者如果它是动态的,将组件添加到 entryComponent
app.module.ts
import { COMPONENT } from './..dir../component'
@NgModule({
declarations: [COMPONENT],
/.
..
..
./
entryComponents: [COMPONENT]
});
html
<ng-container *ngComponentOutlet="option.component"></ng-container>
.ts
/** The COMPONENT is not imported since it is added to entrycomponent**/
@Input() option;