Angular2:以编程方式创build子组件

如何在父组件内创build子组件,然后使用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. // Eg 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文档预览中find了DynamicComponentLoader 。 但是在下面的例子中我得到了下面的错误: 元素0没有dynamic组件指令

这通常不是我会采取的方法。 相反,我会依靠数据绑定对象将呈现出更多的子组件,因为对象被添加到支持数组。 基本上是用ng-for包装的子组件

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

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

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

在Angular 2.0中, DynamicComponentLoader loadIntoLocation方法实现了创build父子关系的目的。 通过使用这种方法,您可以dynamic创build两个组件之间的关系。

这里是是我的父母和公告是我的孩子组件的示例代码。

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> 

在这个答案中提到了你需要照顾的几件事情

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

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

把上面的代码放到你的ngOnInit函数中,用你的组件名称replace“SpreadSheetComponent”。

希望这会工作。

正确的做法取决于你想要解决的情况。

如果孩子的数量不详,那么NgFor就是正确的做法。 如果它是固定的,正如你所提到的,3个孩子,你可以使用DynamicComponentLoader手动加载它们。 手动加载的好处是更好地控制父元素中的元素和对它们的引用(也可以使用模板来获取它们)

如果您需要使用数据填充孩子,这也可以通过注射来完成,Parent将使用填充孩子的数据对象注入…

再次,很多select。 我在我的模式示例中使用了“DynamicComponentLoader”, https://github.com/shlomiassaf/angular2-modal

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

我们需要使用ngAfterContentInit()生命周期方法。 它在指令内容被完全初始化之后被调用。

parent-component.html ,添加一个像这样的div

<div #container> </div>

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()的方法,它需要一个组件工厂作为parameter passing。 同样,我们需要注入一个ComponentFactoryResolver 。 它有一个基本上加载组件的方法。