Angular是否支持递归嵌套动态组件?

时间:2018-07-19 12:40:36

标签: angular

这是我可以找到的唯一指南。

https://angular.io/guide/dynamic-component-loader

我使用的是相同的方法,所以一切都非常基础。直到有了递归组件。

让我们想象一下这种数据形状:

{
   component: {
       id: "container",
       components: [
           {
              id: "container",
              components: [
                  {
                       id: "text",
                       data: "Hi"
                  }
              ]
           }
       ]
   }
}

这是什么意思:

  1. Container需要访问DynamicComponentLoader
  2. DynamicComponentLoader可以构建Container
  3. 请参阅第一步。

Angular警告我存在循环依赖,这是正确的。

但是我在这个问题上花了一个星期,我绝对看不到解决方案。我认为我将不得不停止使用动态组件,而不得不返回使用@Input。像ButtonContainerImageContainer等。我似乎无法制作一个通用容器。我被卡在平坦的表面上。

那真是痛苦。有人有什么想法吗?

1 个答案:

答案 0 :(得分:1)

我按照@OP的要求发表评论作为答案。

official angular documentation中有一个很好的示例,说明如何创建动态组件。基本上,它包含一个组件(AdBannerComponent),可以使用ComponentFactoryResolver从给定列表中创建组件。

基于此示例,我们可以创建一个仅重用AdBannerComponent的新组件:

import { Component, Input, ComponentFactoryResolver, ViewChild, OnInit } from '@angular/core';
import { AdComponent } from './ad.component';
import { AdItem } from './ad-item';
import { AdDirective } from './ad.directive';
@Component({
  template: `
    <div class="job-ad">
    <app-ad-banner [ads]="ads"></app-ad-banner>
    </div>
`})
export class HeroSubProfileComponent implements AdComponent, OnInit {
  @Input() data: any;
  ads: AdItem[];
  constructor() { }
  ngOnInit() {
    this.ads = this.data;
  }
}

此组件将动态创建在data中作为输入给出的组件。我们还可以通过更新其定义以匹配AdBannerComponent来直接重用AdItem

export class AdBannerComponent implements OnInit, OnDestroy {
  @Input() ads: AdItem[];
  currentAdIndex = -1;
  @ViewChild(AdDirective) adHost: AdDirective;
  interval: any;
  @Input() data: any;

  constructor(private componentFactoryResolver: ComponentFactoryResolver) { }

  ngOnInit() {
    if (this.data != null) {
      this.ads = this.data;
    }
    this.loadComponent();
    this.getAds();
  }

如果我们使用以下内容更新AdService(提供要创建的组件列表):

@Injectable()
export class AdService {
  getAds() {
    return [
      new AdItem(HeroProfileComponent, {name: 'Bombasto', bio: 'Brave as they come'}),

      new AdItem(HeroProfileComponent, {name: 'Dr IQ', bio: 'Smart as they come'}),

      new AdItem(HeroJobAdComponent,   {headline: 'Hiring for several positions',
                                        body: 'Submit your resume today!'}),

      new AdItem(HeroJobAdComponent,   {headline: 'Openings in all departments',
                                        body: 'Apply today'}),
      // component using composition
      new AdItem(HeroSubProfileComponent, [new AdItem(HeroProfileComponent, {name: 'Great Scott', bio: 'Awesome'})]),
      // directly using AdBannerComponent
      new AdItem(AdBannerComponent, [new AdItem(HeroProfileComponent, {name: 'Bombasto', bio: 'Brave as they come'})])
    ];
  }
}

我们正在另一个内部创建动态组件,我们可以根据需要做得更深。

您可以在https://stackblitz.com/edit/angular-dsivwn上找到正在运行的示例。