您的位置:首页 > Web前端 > AngularJS

dynamic - How to angular 2 dynamic tabs with user click chosen components

2016-07-15 15:32 603 查看
Code Snippet: https://plnkr.co/edit/kVJvI1vkzrLZJeRFsZuv?p=preview
Update - use ViewContainerRef.createComponent()

Because 
DynamicComponentLoader
 is deprecated, the approach needs to be update again.
@Component({
selector: 'dcl-wrapper',
template: `<div #target></div>`
})
export class DclWrapper {
@ViewChild('target', {read: ViewContainerRef}) target;
@Input() type;
cmpRef:ComponentRef;
private isViewInitialized:boolean = false;

constructor(private resolver: ComponentResolver) {}

updateComponent() {
if(!this.isViewInitialized) {
return;
}
if(this.cmpRef) {
this.cmpRef.destroy();
}
this.resolver.resolveComponent(this.type).then((factory:ComponentFactory<any>) => {
this.cmpRef = this.target.createComponent(factory)
// to access the created instance use
// this.compRef.instance.someProperty = 'someValue';
// this.compRef.instance.someOutput.subscribe(val => doSomething());
});
}

ngOnChanges() {
this.updateComponent();
}

ngAfterViewInit() {
this.isViewInitialized = true;
this.updateComponent();
}

ngOnDestroy() {
if(this.cmpRef) {
this.cmpRef.destroy();
}
}
}


Update - use loadNextToLocation
export class DclWrapper {
@ViewChild('target', {read: ViewContainerRef}) target;
@Input() type;
cmpRef:ComponentRef;
private isViewInitialized:boolean = false;

constructor(private dcl:DynamicComponentLoader) {}

updateComponent() {
// should be executed every time `type` changes but not before `ngAfterViewInit()` was called
// to have `target` initialized
if(!this.isViewInitialized) {
return;
}
if(this.cmpRef) {
this.cmpRef.destroy();
}
this.dcl.loadNextToLocation(this.type, this.target).then((cmpRef) => {
this.cmpRef = cmpRef;
});
}

ngOnChanges() {
this.updateComponent();
}

ngAfterViewInit() {
this.isViewInitialized = true;
this.updateComponent();
}

ngOnDestroy() {
if(this.cmpRef) {
this.cmpRef.destroy();
}
}
}


original

Not entirely sure from your question what your requirements are but I think this should do what you want.

The 
Tabs
 component gets an array of types passed and it creates "tabs" for each item in the array.
@Component({
selector: 'dcl-wrapper',
template: `<div #target></div>`
})
export class DclWrapper {
constructor(private elRef:ElementRef, private dcl:DynamicComponentLoader) {}
@Input() type;

ngOnChanges() {
if(this.cmpRef) {
this.cmpRef.dispose();
}
this.dcl.loadIntoLocation(this.type, this.elRef, 'target').then((cmpRef) => {
this.cmpRef = cmpRef;
});
}
}

@Component({
selector: 'c1',
template: `<h2>c1</h2>`

})
export class C1 {
}

@Component({
selector: 'c2',
template: `<h2>c2</h2>`

})
export class C2 {
}

@Component({
selector: 'c3',
template: `<h2>c3</h2>`

})
export class C3 {
}

@Component({
selector: 'my-tabs',
directives: [DclWrapper],
template: `
<h2>Tabs</h2>
<div *ngFor="let tab of tabs">
<dcl-wrapper [type]="tab"></dcl-wrapper>
</div>
`
})
export class Tabs {
@Input() tabs;
}

@Component({
selector: 'my-app',
directives: [Tabs]
template: `
<h2>Hello {{name}}</h2>
<my-tabs [tabs]="types"></my-tabs>
`
})
export class App {
types = [C3, C1, C2, C3, C3, C1, C1];
}


(not based on your Plunker)

There is also a way to pass data along that can be passed to the dynamically created component like (
someData
 would need to be passed like 
type
)
this.dcl.loadIntoLocation(this.type, this.elRef, 'target').then((cmpRef) => {
cmpRef.instance.someProperty = someData;
this.cmpRef = cmpRef;
});


There is also some support to use dependency injection with shared services.

For more details see https://angular.io/docs/js/latest/api/core/DynamicComponentLoader-class.html
原文链接: http://stackcode.xyz/sc?id=is36325212
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: