【问题标题】:Angular2: Creating child components programmaticallyAngular2:以编程方式创建子组件
【发布时间】:2015-08-30 02:03:23
【问题描述】:

问题

如何在父组件中创建子组件,然后使用 Angular2 在视图中显示它们?如何确保注入物正确注入子组件?

示例

import {Component, View, bootstrap} from 'angular2/angular2';
import {ChildComponent} from './ChildComponent';

@Component({
    selector: 'parent'
})
@View({
  template: `
    <div>
      <h1>the children:</h1>
      <!-- ??? three child views shall be inserted here ??? -->
    </div>`,
  directives: [ChildComponent]
})
class ParentComponent {

        children: ChildComponent[];

        constructor() {
            // when creating the children, their constructors
            // shall still be called with the injectables.
            // E.g. constructor(childName:string, additionalInjectable:SomeInjectable)
            children.push(new ChildComponent("Child A"));
            children.push(new ChildComponent("Child B"));
            children.push(new ChildComponent("Child C"));
            // How to create the components correctly?
        }
}
bootstrap(ParentComponent);

编辑

我在API docs preview 中找到了DynamicComponentLoader。但是在执行示例时出现以下错误:在元素 0 处没有动态组件指令

【问题讨论】:

标签: javascript angular typescript


【解决方案1】:

这通常不是我会采取的方法。相反,我将依赖对一个数组的数据绑定,该数组将在将对象添加到支持数组时呈现出更多子组件。本质上是包裹在 ng-for 中的子组件

我这里有一个类似的例子,它呈现一个动态的子列表。不是 100% 相同,但似乎概念仍然相同:

http://www.syntaxsuccess.com/viewarticle/recursive-treeview-in-angular-2.0

【讨论】:

  • 很好的例子,还不确定,如果它回答了我的问题。我对语法有一些后续问题,我将其作为文章下方的评论发布。基本上我找不到以下任何文档。在模板中:[directories]="directories"、[checked]="dir.checked" 或 (click)="dir.check()"。在组件中 properties: ['directories:directories'] ...这些东西怎么称呼?我在哪里可以了解它们?
  • 我已对您的评论添加了回复
  • 添加一些关于为什么This is generally not the approach I would take 可能对人们有所帮助的信息
【解决方案2】:

警告:DynamicComponentLoader 在 RC.4 中已被弃用

在 Angular 2.0 中,DynamicComponentLoader 的 loadIntoLocation 方法用于创建父子关系。通过使用这种方法,您可以动态地创建两个组件之间的关系。

这是示例代码,其中 paper 是我的父组件,bulletin 是我的子组件。

paper.component.ts

import {Component,DynamicComponentLoader,ElementRef,Inject,OnInit} from 'angular2/core';
import { BulletinComponent } from './bulletin.component';

@Component({
    selector: 'paper',
    templateUrl: 'app/views/paper.html'

    }
})
export class PaperComponent {
    constructor(private dynamicComponentLoader:DynamicComponentLoader, private elementRef: ElementRef) {

    }

    ngOnInit(){
        this.dynamicComponentLoader.loadIntoLocation(BulletinComponent, this.elementRef,'child');

    }
}

bulletin.component.ts

import {Component} from 'angular2/core';

@Component({
    selector: 'bulletin',
    template: '<div>Hi!</div>'
    }
})
export class BulletinComponent {}

paper.html

<div>
    <div #child></div>
</div>

Few things you needs to be take care of are mentioned in this answer

【讨论】:

  • 能否提供弃用文档的链接?
【解决方案3】:

你应该使用 ComponentFactoryResolver 和 ViewElementRef 在运行时添加组件。让我们看看下面的代码。

let factory = this.componentFactoryResolver.resolveComponentFactory(SpreadSheetComponent);
let res = this.viewContainerRef.createComponent(factory);

将上述代码放入您的 ngOnInit 函数中,并将“SpreadSheetComponent”替换为您的组件名称。

希望这会奏效。

【讨论】:

    【解决方案4】:

    在 Angular 2/4 应用程序中以编程方式将组件添加到 DOM

    我们需要使用来自AfterContentInit 的ngAfterContentInit() 生命周期方法。指令内容完全初始化后调用。

    在parent-component.html 中,添加div,如下所示:

    &lt;div #container&gt; &lt;/div&gt;

    parent-component.ts 文件如下所示:

    
    
    class ParentComponent implements AfterContentInit {
    
      @ViewChild("container", { read: ViewContainerRef }) divContainer
    
      constructor(private componentFactoryResolver: ComponentFactoryResolver) { }
    
      ngAfterContentInit() {
        let childComponentFactory = this.componentFactoryResolver.resolveComponentFactory(childComponent);
        this.divContainer.createComponent(childComponentFactory);
        let childComponentRef = this.divContainer.createComponent(childComponentFactory);
        childComponentRef.instance.someInputValue = "Assigned value";
    
      }
    }
    

    在src\app\app.module.ts 中,将以下条目添加到@NgModule() 方法参数中:

    
      entryComponents:[
        childComponent
      ],
    

    请注意,我们没有使用@ViewChild("container") divContainer 方法访问div#container。我们需要它的参考而不是nativeElement。我们将以ViewContainerRef 访问它:

    @ViewChild("container", {read: ViewContainerRef}) divContainer

    ViewContainerRef 有一个名为createComponent() 的方法,它需要将组件工厂作为参数传递。同样,我们需要注入一个ComponentFactoryResolver。它有一个基本上加载组件的方法。

    【讨论】:

      【解决方案5】:

      正确的方法取决于您要解决的情况。

      如果孩子的数量未知,那么 NgFor 是正确的方法。 如果它是固定的,正如你提到的,3 个孩子,你可以使用 DynamicComponentLoader 手动加载它们。 手动加载的好处是可以更好地控制元素以及在 Parent 中对它们的引用(也可以使用模板获得...)

      如果您需要用数据填充子级,这也可以通过注入来完成,父级被注入一个数据对象来填充子级......

      同样,有很多选择。 我在模态示例中使用了“DynamicComponentLoader”https://github.com/shlomiassaf/angular2-modal

      【讨论】:

        猜你喜欢
        • 2016-05-26
        • 2012-01-12
        • 2014-09-26
        • 1970-01-01
        • 2012-09-09
        • 2016-05-01
        • 2015-02-25
        • 1970-01-01
        相关资源
        最近更新 更多