加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

带用户单击所选组件的Angular 2动态选项卡

发布时间:2020-12-17 09:09:30 所属栏目:安全 来源:网络整理
导读:我试图设置一个标签系统,允许组件注册自己(带有标题)。第一个标签就像一个收件箱,有很多操作/链接项供用户选择,每次点击都应该能够点击实例化一个新的组件。操作/链接来自JSON。 实例化的组件然后将其自身注册为新的选项卡。 我不知道这是否是“最好的”
我试图设置一个标签系统,允许组件注册自己(带有标题)。第一个标签就像一个收件箱,有很多操作/链接项供用户选择,每次点击都应该能够点击实例化一个新的组件。操作/链接来自JSON。

实例化的组件然后将其自身注册为新的选项卡。

我不知道这是否是“最好的”方法? Sofar我看到的唯一指南是静态选项卡,这没有什么帮助。

到目前为止,我只有标签服务,这是bootstrap在主要持久整个应用程序,看起来像这样的东西。

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获取并显示几个项目。单击其中一个项目后,将创建一个带有该项目操作“type”的新选项卡。类型是一个组件

编辑2:图像

http://i.imgur.com/yzfMOXJ.png

更新

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,C1];
}
@NgModule({
  imports: [ BrowserModule ],declarations: [ App,DclWrapper,Tabs,C3],entryComponents: [C1,bootstrap: [ App ]
})
export class AppModule {}

旧版本xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

这在Angular2 RC.5中再次改变

我将更新下面的例子,但它是度假前的最后一天。

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

更新 – 使用ViewContainerRef.createComponent()

因为不推荐使用DynamicComponentLoader,所以该方法需要重新更新。

@Component({
  selector: 'dcl-wrapper',{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];
}

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

还有一种方法来传递数据,可以传递到动态创建的组件像(someData将需要像类型传递)

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

还有一些支持使用共享服务来使用依赖注入。

详情请参阅https://angular.io/docs/js/latest/api/core/DynamicComponentLoader-class.html

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读