angular 5动态模块中的递归指令(没有循环依赖)

时间:2018-03-05 15:29:00

标签: angular angular5

我正在尝试将动态模板加载到角度5应用中。 首先尝试的是角度文档中的示例,https://angular.io/guide/dynamic-component-loader这是一个死胡同,因为它所做的只是动态加载静态组件。

第二次是来自AngularInDepth.com Max NgWizard K的博客文章 https://blog.angularindepth.com/here-is-what-you-need-to-know-about-dynamic-components-in-angular-ac1e96167f9e

这就像一个动态渲染模板的魅力。但是,我试图连接我的动态组件进行递归调用甚至加载常用模块。

查看stackoverflow,大多数答案都已过时,但是没有工作的掠夺者和少数工作并没有真正解决循环依赖问题,甚至加载模块,除了在我的情况下已经工作的插值。

我已经分叉了一个角度docs项目来演示问题https://stackblitz.com/edit/angular-aa3ah1?file=src%2Fapp%2Fheroes%2Fheroes.component.ts

import { Component, OnInit, Input, ViewChild, Compiler, NgModule } from '@angular/core';
import { ViewContainerRef } from '@angular/core';
import { Portal } from './portal'
import { SharedModule } from './shared.module'
@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {

  @Input() msg: any;
  @ViewChild('vc', {read: ViewContainerRef}) vc: ViewContainerRef;


  templates = [//interpolation works without a problem
                `<span> 
                  This works:  {{msg.comment}}
                </span>`,
                // How to import a directive in the template?
                `<span *ngFor="let comment of msg.childComments"> 
                  Directive :  {{comment.comment}}
                </span>`,
                // How to reuse the portal without circular dependancies???
                `<span> 
                  This does not work because app-heroes
                   is not accessible and importing module causes circular dependancies
                   {{msg.comment}}
                </span>
                <span *ngFor="let comment of msg.childComments">
                  <app-heroes [msg]="comment"></app-heroes>
                </span>

                `];

  constructor(private _compiler: Compiler) { }

  ngOnInit() {
    this.loadTemplate(this.templates[0], this.msg, this.vc, this._compiler);
  }

  loadTemplate(myTemplate: string, data: any, vc: ViewContainerRef, compiler: Compiler){
    const portal = Component({template: myTemplate})(Portal);
    //const pModule = NgModule({declarations: [portal], imports: [HeroesComponent]})(class{});
    const pModule = NgModule({declarations: [portal], imports: [SharedModule]})(class{});

    compiler.compileModuleAndAllComponentsAsync(pModule)
        .then((factories) => {
        const f = factories.componentFactories[0];
        const cmpRef = vc.createComponent(f);
        cmpRef.instance.msg = data;
    });
  }
}
  1. 如何让我的动态组件(模板[1])中使用通用模块?
  2. 如何重用动态组件来制作递归指令(模板[2])?

1 个答案:

答案 0 :(得分:1)

  

如何让我的动态组件(模板[1])中使用通用模块?

CommonModule包含NgFor指令,因此直接导入该模块:

import { CommonModule } from '@angular/common';

//...

const pModule = NgModule({declarations: [portal], imports: [SharedModule, CommonModule]})(class{});

但我可能会创建另一个模块,从CommonModule导入NgForOf,将其添加到声明和导出数组。然后改为导入该模块,因此无需从CommonModule导入整个库。

修改

好的,我明白了。但是,你仍然不能在它的孩子身上使用<parent-comp></parent-comp>,因为它会以无限循环结束。如果不考虑重构,我可能会这样:

通知Portal.ts有关评论:

<span *ngFor="let comment of msg.childComments">
  <span msg="comment"></span>
</span>
// but note that msg will refer to the last item from ngFor

检查是否有任何childComments,如果有,请通过EventEmitter或服务调用HeroesComponent loadTemplate()方法。