Angular2:以编程方式创建子组件
Angular2: Creating child components programmatically
问题
如何使用 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
没有动态组件指令
这通常不是我会采用的方法。相反,我会依赖于一个数组的数据绑定,当对象被添加到支持数组时,该数组将渲染出更多的子组件。本质上是包裹在 ng-for
中的子组件
我这里有一个示例,它呈现一个动态的子列表。不是 100% 相同,但似乎概念仍然相同:
http://www.syntaxsuccess.com/viewarticle/recursive-treeview-in-angular-2.0
正确的方法取决于您要解决的情况。
如果 children 的数量未知,那么 NgFor 是正确的方法。
如果它是固定的,正如你提到的,3 children,你可以使用 DynamicComponentLoader
手动加载它们。
手动加载的好处是更好地控制元素并在 Parent 中引用它们(也可以使用模板获得...)
如果你需要用数据填充children,这也可以通过注入来完成,Parent被注入数据object填充children到位...
同样,有很多选择。
我在模态示例中使用了 'DynamicComponentLoader',https://github.com/shlomiassaf/angular2-modal
警告:RC.4 中已弃用 DynamicComponentLoader
在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>
您应该使用 ComponentFactoryResolver 和 ViewElementRef 在 runtime.Let 处添加组件,看看下面的代码。
let factory = this.componentFactoryResolver.resolveComponentFactory(SpreadSheetComponent);
let res = this.viewContainerRef.createComponent(factory);
将上面的代码放在你的 ngOnInit 函数中,并将 "SpreadSheetComponent" 替换为你的组件名称。
希望这会奏效。
在 Angular 2/4 app
中以编程方式将组件添加到 DOM
我们需要使用 AfterContentInit
中的 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()
的方法,它需要将组件工厂作为参数传递。同样,我们需要注入一个ComponentFactoryResolver
。它有一个基本上加载组件的方法。
问题
如何使用 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
这通常不是我会采用的方法。相反,我会依赖于一个数组的数据绑定,当对象被添加到支持数组时,该数组将渲染出更多的子组件。本质上是包裹在 ng-for
中的子组件我这里有一个示例,它呈现一个动态的子列表。不是 100% 相同,但似乎概念仍然相同:
http://www.syntaxsuccess.com/viewarticle/recursive-treeview-in-angular-2.0
正确的方法取决于您要解决的情况。
如果 children 的数量未知,那么 NgFor 是正确的方法。
如果它是固定的,正如你提到的,3 children,你可以使用 DynamicComponentLoader
手动加载它们。
手动加载的好处是更好地控制元素并在 Parent 中引用它们(也可以使用模板获得...)
如果你需要用数据填充children,这也可以通过注入来完成,Parent被注入数据object填充children到位...
同样,有很多选择。 我在模态示例中使用了 'DynamicComponentLoader',https://github.com/shlomiassaf/angular2-modal
警告:RC.4 中已弃用 DynamicComponentLoader
在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>
您应该使用 ComponentFactoryResolver 和 ViewElementRef 在 runtime.Let 处添加组件,看看下面的代码。
let factory = this.componentFactoryResolver.resolveComponentFactory(SpreadSheetComponent);
let res = this.viewContainerRef.createComponent(factory);
将上面的代码放在你的 ngOnInit 函数中,并将 "SpreadSheetComponent" 替换为你的组件名称。
希望这会奏效。
在 Angular 2/4 app
中以编程方式将组件添加到 DOM我们需要使用 AfterContentInit
中的 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()
的方法,它需要将组件工厂作为参数传递。同样,我们需要注入一个ComponentFactoryResolver
。它有一个基本上加载组件的方法。