代码之家  ›  专栏  ›  技术社区  ›  Josef Katič

动态创建的组件中未触发ngOnInit

  •  0
  • Josef Katič  · 技术社区  · 7 年前

    ngOnInit 在创建的组件中没有调用。

    SelectBoardComponent )第二个是董事会本身( BoardComponent 选择BoardComponent 到 一切正常。但当我重新加载或直接访问 板组件 在动态添加的子对象中不会触发整个角度循环(OnInit…)。

    我在网上转载了这一期 stackblitz

    代码

    为了找出我想要创建的组件,我创建了一个“组件注册表”,在这里我注册了每个可以动态呈现的组件。

    import {Type} from '@angular/core';
    
    type ComponentClass = Type<any>;
    
    const REGISTRY = new Map<string, ComponentClass>();
    
    export const getTypeFor = (name: string): ComponentClass => {
      return REGISTRY.get(name);
    };
    export const Register = () => {
      return (cls: ComponentClass) => {
        REGISTRY.set(cls.name, cls);
      };
    };
    

    所以我注册了 InfoCardComponent 我要渲染的组件之一

    import { Component, OnInit } from '@angular/core';
    import {Register} from '../register';
    
    @Component({
      selector: 'app-info-card',
      templateUrl: './info-card.component.html',
      styleUrls: ['./info-card.component.css']
    })
    @Register()
    export class InfoCardComponent implements OnInit {
      public called = "not called!";
      constructor() { }
    
      ngOnInit() {
        this.called = "called!";
      }
    }
    

    在 我补充说 appRender

    这个 附着体 处理生成组件的过程。 我基于JSON数据呈现组件。

      private components = [
      {
        "id": 0,
        "position": 0,
        "cells": [
          {
            "id": "info",
            "title": "Info panel",
            "component": "InfoCardComponent",
            "childs": []
          }
        ]
      }
    ];
      private componentsRef = {};
    
      constructor(
        private appRef: ApplicationRef,
        private injector: Injector,
        private componentFactory: ComponentFactoryResolver,
        private renderer: Renderer2,
        private el: ElementRef) {
      }
    
      ngOnInit() {
          this.el.nativeElement.innerHTML = '';
          const {rows} = this.render();
          for (const row of rows) {
            this.renderer.appendChild(this.el.nativeElement, row);
          }
      }
    
      render() {
        const grid = {rows: []};
        for (const c of this.components) {
          const cells = c.cells;
          if (cells.length > 0) {
            const row = this.renderer.createElement('div');
            for (const {component} of cells) {
              const cell = this.renderer.createElement('div');
              const card = this.renderer.createElement('div');
              this.renderer.appendChild(card, this.createAngularComponent(component).elem);
              this.renderer.appendChild(cell, card);
              this.renderer.appendChild(row, cell);
            }
            grid.rows.push(row);
          }
        }
        return grid;
      }
      private createAngularComponent(parentComponent) {
        const componentElem = this.componentFactory.resolveComponentFactory(getTypeFor(parentComponent)).create(this.injector);
        this.componentsRef[parentComponent] = componentElem;
        this.appRef.attachView(componentElem.hostView);
        return {
          elem: (componentElem.hostView as EmbeddedViewRef<any>).rootNodes[0] as HTMLElement,
        };
      }
    

    所以我的问题是:

    这是预期的行为还是我忘了什么?

    1 回复  |  直到 7 年前
        1
  •  2
  •   Gregor Doroschenko    7 年前

    你有生命周期书的问题。您不能访问中的ElementRef和TemplateRef ngOnInit() ngAfterViewInit() 生命周期手册。把你的逻辑从 到 .

    怎么办:

    恩戈尼尼特() 到 :

    ngAfterViewInit() {
          setTimeout(() => {
            this.el.nativeElement.innerHTML = '';
            const {rows} = this.render();
            for (const row of rows) {
              this.renderer.appendChild(this.el.nativeElement, row);
            }
          }, 0)
      }
    

    setTimeout()

    AfterViewInit 把它从 @angular/core

    推荐文章