代码之家  ›  专栏  ›  技术社区  ›  zer0

在ngif中动态创建组件

  •  2
  • zer0  · 技术社区  · 8 年前

    我用的是角6,我试着按照答案来做 here 但我不能让它工作

    export class AppComponent implements AfterContentInit, AfterViewInit {
      defaultToTrue = true;
      @ViewChildren('parent', { read: ViewContainerRef }) parent: QueryList<ViewContainerRef>;
    
      constructor(private cfr: ComponentFactoryResolver) { }
    
      ngAfterViewInit(){
        const resolve = this.cfr.resolveComponentFactory(ChildComponent);
        this.parent.changes.subscribe(changes => {
          this.parent.createComponent(resolve); //Error
        });
      }
    
    }
    

    HTML:

    <div *ngIf="defaultToTrue">
      <div #parent></div>
    </div>
    

    StackBlitz

    2 回复  |  直到 8 年前
        1
  •  3
  •   ConnorsFan    8 年前

    为了摆脱 ExpressionChangedAfterItHasBeenCheckedError 您可以使用其中的一种技术 this Angular In Depth blog post :

    力变化检测 ChangeDetectorRef.detectChanges :

    constructor(private cfr: ComponentFactoryResolver, private cd: ChangeDetectorRef) { }
    
    ngAfterViewInit(){
      const resolve = this.cfr.resolveComponentFactory(ChildComponent);
      this.parent.changes.subscribe(changes => {
        this.parent.createComponent(resolve);
        this.cd.detectChanges();  // Trigger change detection
      });
    }
    

    使用异步创建组件 setTimeout :

    ngAfterViewInit(){
      const resolve = this.cfr.resolveComponentFactory(ChildComponent);
      this.parent.changes.subscribe(changes => {
        setTimeout(() => { this.parent.createComponent(resolve); });
      });
    }
    
        2
  •  0
  •   bresleveloper    7 年前

    我的案子是 #container 在2里面 *ngFor 以及里面的一切 *ngIf

    我唯一能得到 ViewContainerRef QueryList<ViewContainerRef> 是在 ngAfterViewChecked ,并且仅在条件内,甚至在 setTimeout

    编辑:必须添加标志才能停止,否则将无休止地运行

    if (this.fieldsContainer && this.componentsGenerated == false) {
      this.componentsGenerated = true
      setTimeout(this.generateComponents.bind(this))
    }
    

    编辑2: 最终需要更多的代码来处理这些问题并使用 changeDetection: ChangeDetectionStrategy.OnPush 具有 cd:ChangeDetectorRef

    ngAfterViewChecked(): void {
    
      if (this.fieldsContainersQuery && this.componentsGenerated == false) {
        this.componentsGenerated = true
    
        this.fieldsContainersQuery.changes.subscribe(changes=>{
          this.fieldsContainersQuery.forEach(fieldContainerItem => this.generateComponents(fieldContainerItem))
          this.cd.detectChanges()
       })
     }
    

    更多细节

    blog github

    推荐文章