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

前端之家收集整理的这篇文章主要介绍了带用户单击所选组件的Angular 2动态选项卡前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图设置一个标签系统,允许组件注册自己(带有标题)。第一个标签就像一个收件箱,有很多操作/链接项供用户选择,每次点击都应该能够点击实例化一个新的组件。操作/链接来自JSON。

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

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

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

  1. export interface ITab { title: string; }
  2.  
  3. @Injectable()
  4. export class TabsService {
  5. private tabs = new Set<ITab>();
  6.  
  7. addTab(title: string): ITab {
  8. let tab: ITab = { title };
  9. this.tabs.add(tab);
  10. return tab;
  11. }
  12.  
  13. removeTab(tab: ITab) {
  14. this.tabs.delete(tab);
  15. }
  16. }

问题:

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

  1. // Helper component to add dynamic components
  2. @Component({
  3. selector: 'dcl-wrapper',template: `<div #target></div>`
  4. })
  5. export class DclWrapper {
  6. @ViewChild('target',{read: ViewContainerRef}) target: ViewContainerRef;
  7. @Input() type: Type<Component>;
  8. cmpRef: ComponentRef<Component>;
  9. private isViewInitialized:boolean = false;
  10.  
  11. constructor(private componentFactoryResolver: ComponentFactoryResolver,private compiler: Compiler) {}
  12.  
  13. updateComponent() {
  14. if(!this.isViewInitialized) {
  15. return;
  16. }
  17. if(this.cmpRef) {
  18. // when the `type` input changes we destroy a prevIoUsly
  19. // created component before creating the new one
  20. this.cmpRef.destroy();
  21. }
  22.  
  23. let factory = this.componentFactoryResolver.resolveComponentFactory(this.type);
  24. this.cmpRef = this.target.createComponent(factory)
  25. // to access the created instance use
  26. // this.compRef.instance.someProperty = 'someValue';
  27. // this.compRef.instance.someOutput.subscribe(val => doSomething());
  28. }
  29.  
  30. ngOnChanges() {
  31. this.updateComponent();
  32. }
  33.  
  34. ngAfterViewInit() {
  35. this.isViewInitialized = true;
  36. this.updateComponent();
  37. }
  38.  
  39. ngOnDestroy() {
  40. if(this.cmpRef) {
  41. this.cmpRef.destroy();
  42. }
  43. }
  44. }

用法示例

  1. // Use dcl-wrapper component
  2. @Component({
  3. selector: 'my-tabs',template: `
  4. <h2>Tabs</h2>
  5. <div *ngFor="let tab of tabs">
  6. <dcl-wrapper [type]="tab"></dcl-wrapper>
  7. </div>
  8. `
  9. })
  10. export class Tabs {
  11. @Input() tabs;
  12. }
  1. @Component({
  2. selector: 'my-app',template: `
  3. <h2>Hello {{name}}</h2>
  4. <my-tabs [tabs]="types"></my-tabs>
  5. `
  6. })
  7. export class App {
  8. // The list of components to create tabs from
  9. types = [C3,C1,C2,C3,C1];
  10. }
  1. @NgModule({
  2. imports: [ BrowserModule ],declarations: [ App,DclWrapper,Tabs,C3],entryComponents: [C1,bootstrap: [ App ]
  3. })
  4. export class AppModule {}

旧版本xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

这在Angular2 RC.5中再次改变

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

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

更新 – 使用ViewContainerRef.createComponent()

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

  1. @Component({
  2. selector: 'dcl-wrapper',{read: ViewContainerRef}) target;
  3. @Input() type;
  4. cmpRef:ComponentRef;
  5. private isViewInitialized:boolean = false;
  6.  
  7. constructor(private resolver: ComponentResolver) {}
  8.  
  9. updateComponent() {
  10. if(!this.isViewInitialized) {
  11. return;
  12. }
  13. if(this.cmpRef) {
  14. this.cmpRef.destroy();
  15. }
  16. this.resolver.resolveComponent(this.type).then((factory:ComponentFactory<any>) => {
  17. this.cmpRef = this.target.createComponent(factory)
  18. // to access the created instance use
  19. // this.compRef.instance.someProperty = 'someValue';
  20. // this.compRef.instance.someOutput.subscribe(val => doSomething());
  21. });
  22. }
  23.  
  24. ngOnChanges() {
  25. this.updateComponent();
  26. }
  27.  
  28. ngAfterViewInit() {
  29. this.isViewInitialized = true;
  30. this.updateComponent();
  31. }
  32.  
  33. ngOnDestroy() {
  34. if(this.cmpRef) {
  35. this.cmpRef.destroy();
  36. }
  37. }
  38. }

Plunker example RC.4
Plunker example beta.17

更新 – 使用loadNextToLocation

  1. export class DclWrapper {
  2. @ViewChild('target',{read: ViewContainerRef}) target;
  3. @Input() type;
  4. cmpRef:ComponentRef;
  5. private isViewInitialized:boolean = false;
  6.  
  7. constructor(private dcl:DynamicComponentLoader) {}
  8.  
  9. updateComponent() {
  10. // should be executed every time `type` changes but not before `ngAfterViewInit()` was called
  11. // to have `target` initialized
  12. if(!this.isViewInitialized) {
  13. return;
  14. }
  15. if(this.cmpRef) {
  16. this.cmpRef.destroy();
  17. }
  18. this.dcl.loadNextToLocation(this.type,this.target).then((cmpRef) => {
  19. this.cmpRef = cmpRef;
  20. });
  21. }
  22.  
  23. ngOnChanges() {
  24. this.updateComponent();
  25. }
  26.  
  27. ngAfterViewInit() {
  28. this.isViewInitialized = true;
  29. this.updateComponent();
  30. }
  31.  
  32. ngOnDestroy() {
  33. if(this.cmpRef) {
  34. this.cmpRef.destroy();
  35. }
  36. }
  37. }

Plunker example beta.17

原版的

不完全确定从你的问题你的要求是什么,但我认为这应该做你想要的。

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

  1. @Component({
  2. selector: 'dcl-wrapper',template: `<div #target></div>`
  3. })
  4. export class DclWrapper {
  5. constructor(private elRef:ElementRef,private dcl:DynamicComponentLoader) {}
  6. @Input() type;
  7.  
  8. ngOnChanges() {
  9. if(this.cmpRef) {
  10. this.cmpRef.dispose();
  11. }
  12. this.dcl.loadIntoLocation(this.type,this.elRef,'target').then((cmpRef) => {
  13. this.cmpRef = cmpRef;
  14. });
  15. }
  16. }
  17.  
  18. @Component({
  19. selector: 'c1',template: `<h2>c1</h2>`
  20.  
  21. })
  22. export class C1 {
  23. }
  24.  
  25. @Component({
  26. selector: 'c2',template: `<h2>c2</h2>`
  27.  
  28. })
  29. export class C2 {
  30. }
  31.  
  32. @Component({
  33. selector: 'c3',template: `<h2>c3</h2>`
  34.  
  35. })
  36. export class C3 {
  37. }
  38.  
  39. @Component({
  40. selector: 'my-tabs',directives: [DclWrapper],template: `
  41. <h2>Tabs</h2>
  42. <div *ngFor="let tab of tabs">
  43. <dcl-wrapper [type]="tab"></dcl-wrapper>
  44. </div>
  45. `
  46. })
  47. export class Tabs {
  48. @Input() tabs;
  49. }
  50.  
  51.  
  52. @Component({
  53. selector: 'my-app',directives: [Tabs]
  54. template: `
  55. <h2>Hello {{name}}</h2>
  56. <my-tabs [tabs]="types"></my-tabs>
  57. `
  58. })
  59. export class App {
  60. types = [C3,C1];
  61. }

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

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

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

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

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

猜你在找的Angularjs相关文章