gpt4 book ai didi

angular - 带有用户单击选定组件的动态选项卡

转载 作者:太空狗 更新时间:2023-10-29 16:44:12 25 4
gpt4 key购买 nike

我正在尝试设置一个允许组件自行注册(带有标题)的选项卡系统。第一个选项卡就像一个收件箱,有很多操作/链接项可供用户选择,每次点击都应该能够在点击时实例化一个新组件。操作/链接来自 JSON。

然后实例化的组件将自己注册为一个新选项卡。

我不确定这是否是“最佳”方法?到目前为止,我看到的唯一指南是针对静态选项卡的,这没有帮助。

到目前为止,我只获得了在 main 中引导以在整个应用程序中持续存在的选项卡服务。它看起来像这样:

export interface ITab { title: string; }

@Injectable()
export class TabsService {
private tabs = new Set<ITab>();

addTab(title: string): ITab {
let tab: ITab = { title };
this.tabs.add(tab);
return tab;
}

removeTab(tab: ITab) {
this.tabs.delete(tab);
}
}

问题:

  1. 如何在收件箱中创建一个动态列表来创建新的(不同的)标签?我猜会使用 DynamicComponentBuilder 吗?
  2. 如何从收件箱创建组件(单击时)将它们自己注册为选项卡并显示?我猜 ng-content,但我找不到太多关于如何使用它的信息

编辑:试图澄清。

将收件箱想象成邮件收件箱。项目以 JSON 格式获取,并显示多个项目。单击其中一个项目后,将使用该项目操作“类型”创建一个新选项卡。该类型就是一个组件。

编辑 2: Image .

最佳答案

更新

Angular 5 StackBlitz example

更新

ngComponentOutlet 已添加到 4.0.0-beta.3

更新

有一个 NgComponentOutlet 正在进行中,它做类似的事情 https://github.com/angular/angular/pull/11235

RC.7

Plunker example RC.7

// Helper component to add dynamic components
@Component({
selector: 'dcl-wrapper',
template: `<div #target></div>`
})
export class DclWrapper {
@ViewChild('target', {read: ViewContainerRef}) target: ViewContainerRef;
@Input() type: Type<Component>;
cmpRef: ComponentRef<Component>;
private isViewInitialized:boolean = false;

constructor(private componentFactoryResolver: ComponentFactoryResolver, private compiler: Compiler) {}

updateComponent() {
if(!this.isViewInitialized) {
return;
}
if(this.cmpRef) {
// when the `type` input changes we destroy a previously
// created component before creating the new one
this.cmpRef.destroy();
}

let factory = this.componentFactoryResolver.resolveComponentFactory(this.type);
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();
}
}
}

使用示例

// Use dcl-wrapper component
@Component({
selector: 'my-tabs',
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',
template: `
<h2>Hello {{name}}</h2>
<my-tabs [tabs]="types"></my-tabs>
`
})
export class App {
// The list of components to create tabs from
types = [C3, C1, C2, C3, C3, C1, C1];
}
@NgModule({
imports: [ BrowserModule ],
declarations: [ App, DclWrapper, Tabs, C1, C2, C3],
entryComponents: [C1, C2, C3],
bootstrap: [ App ]
})
export class AppModule {}

另见 angular.io DYNAMIC COMPONENT LOADER

旧版本 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

这在 Angular2 RC.5 中再次改变

我将更新下面的示例,但这是假期前的最后一天。

Plunker example演示如何在 RC.5 中动态创建组件

更新 - 使用 ViewContainerRef .createComponent()

由于 DynamicComponentLoader 已弃用,因此需要再次更新该方法。

@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();
}
}
}

Plunker example RC.4
Plunker example beta.17

更新 - 使用 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();
}
}
}

Plunker example beta.17

原创

从你的问题中不能完全确定你的要求是什么,但我认为这应该可以满足你的要求。

Tabs 组件获取传递的类型数组,并为数组中的每个项目创建“选项卡”。

@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];
}

Plunker example beta.15 (不是基于你的 Plunker)

还有一种传递数据的方法,可以将数据传递给动态创建的组件,例如(someData 需要像 type 一样传递)

    this.dcl.loadIntoLocation(this.type, this.elRef, 'target').then((cmpRef) => {
cmpRef.instance.someProperty = someData;
this.cmpRef = cmpRef;
});

也有一些支持在共享服务中使用依赖注入(inject)。

有关详细信息,请参阅 https://angular.io/docs/ts/latest/cookbook/dynamic-component-loader.html

关于angular - 带有用户单击选定组件的动态选项卡,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36325212/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com