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
。 它有一个基本上加载组件的方法。