Angular2:创建组件实例而不注入它
问题 Angular2中有没有一种方法可以创建组件的实例而不实际注入它?使用ViewContainerRef.insert()或其他类似工具将组件插入到视图中 我知道有DynamicComponentLoader,但它需要一个ViewContainerRef来附加它自己创建的实例。该视图当时甚至不存在 问题是,我想创建视图实例,配置它们(甚至通过自定义工厂),并在其他点将它们添加到任何视图中 有一个ViewContainerRef,它能够在任意索引处插入ViewRef,这到目前为止还不错,但是如何从我创建的组件创建ViewRef而不实际插入它呢 我希望你明白我的问题:p 更新: 一个示例应用程序是通过表单的类似旋转木马的导航。应该创建视图,并且只有具有当前索引的视图才应该加载之前的状态 下面是一个未完成的示例,其中包含一些标记关键位置的TODO(请参见LoadView()和showView(),以了解相关信息)Angular2:创建组件实例而不注入它,angular,components,Angular,Components,问题 Angular2中有没有一种方法可以创建组件的实例而不实际注入它?使用ViewContainerRef.insert()或其他类似工具将组件插入到视图中 我知道有DynamicComponentLoader,但它需要一个ViewContainerRef来附加它自己创建的实例。该视图当时甚至不存在 问题是,我想创建视图实例,配置它们(甚至通过自定义工厂),并在其他点将它们添加到任何视图中 有一个ViewContainerRef,它能够在任意索引处插入ViewRef,这到目前为止还不错,但是如
从'@angular/core'导入{Component,ViewChild,ViewContainerRef,AfterViewInit}
导出接口可存储{
save(transaction:any):void;//transaction通常是一个已定义的类型,但这对于本例来说太过分了
}
@组成部分({
选择器:“用户表单”,
模板:`
用户名:
密码:
`
})
导出类UserForm实现可存储{
public uname:string=null;
public passwd:string=null;
构造函数(){
}
公共保存(事务:任何):无效{
//通过事务保存this.uname(对于本例不重要)
//通过事务保存this.passwd(对于本例不重要)
}
}
@组成部分({
选择器:'地址表单',
模板:`
街道:
城市:
邮政编码:
`
})
导出类AddressForm实现可存储{
公共街道:字符串=null;
公共城市:字符串=null;
公共postalCode:string=null;
构造函数(){
}
公共保存(事务:任何):无效{
//通过事务保存this.street(在本例中不重要)
//通过事务保存this.city(在本例中不重要)
//通过事务保存this.postalCode(在本例中不重要)
}
}
@组成部分({
选择器:“我的应用程序”,
提供者:[],
模板:`
旋转木马/类似Wizzard的状态维护导航
返回
下一个
未加载任何内容
`,
指令:[]
})
导出类应用程序实现AfterViewInit{
@ViewChild('content',{read:ViewContainerRef})content:ViewContainerRef;
私有ci=-1;
私有视图=[];
构造函数(){
这是loadViews();
如果(this.views.length>0){
该系数为0.ci=0;
}
}
public ngAfterViewInit():void{
this.showView(this.ci);
}
//这是第1条的关键部分
public loadViews():void{//这是简化的,在我的例子中,这是通过一个返回“初始化”视图数组的配置加载程序实现的
//我知道这是行不通的!我只是想知道:
var v=新的UserForm();
v、 uname=“某些初始化值”;
v、 passwd=“通常由另一个实例加载”;
本.视图.推送(v);
v=新地址形式();
v、 street=“Examplestreet 15”;
v、 city=“Exampletown”;
v、 postalCode=“12345”;
本.视图.推送(v);
}
受保护的prevBtnClick():void{
if(this.ci<0)
返回;
这个.ci++;
if(this.ci>=this.views.length)
该系数为0.ci=0;
this.showView(this.ci);
}
受保护的nextBtnClick():void{
if(this.ci<0)
返回;
这个.ci--;
if(this.ci<0)
this.ci=this.views.length-1;
this.showView(this.ci);
}
//这是第2条的关键部分
公共showView(索引:编号):无效{
如果(索引<0 | |索引>=this.views.length | |!this.views | | this.views.length==0)
返回;
this.ci=索引;
var view=this.views[index];
//TODO:从此.content中删除当前加载的视图
//TODO:加载此.content中的视图实例,而不创建新实例
//因为必须维护实例的状态!!
}
//对于这个例子来说并不重要
公共保存(事务:任何):无效{
for(此.views的var v)
(:请随意更新示例我不明白为什么使用ViewContainerRef
会出现问题。听起来很类似,因为这种方法是一个工厂,angular为我创建了一个实例。例如,如果我有加载程序创建的视图或类似的视图,它也会初始化视图,这将不起作用!就像在我的旋转木马exa中一样我想预先配置视图(基于配置加载程序),然后根据索引显示正确的视图。视图必须保持其状态!
import {Component, ViewChild, ViewContainerRef, AfterViewInit} from '@angular/core'
export interface Storable {
save(transaction: any): void; //transaction is usually a defined type, but this would go too far for this example
}
@Component({
selector: 'user-form',
template: `<div>
User name: <input type="text" [(ngModel)]="uname" /><br />
Password: <input type="password" [(ngModel)]="passwd" />
</div>`
})
export class UserForm implements Storable {
public uname: string = null;
public passwd: string = null;
constructor() {
}
public save(transaction: any): void {
//save this.uname via transaction (not important for this example)
//save this.passwd via transaction (not important for this example)
}
}
@Component({
selector: 'address-form',
template: `<div>
Street: <input type="text" [(ngModel)]="street" /><br />
City: <input type="password" [(ngModel)]="city" /><br />
Postal Code: <input type="password" [(ngModel)]="postalCode" />
</div>`
})
export class AddressForm implements Storable {
public street: string = null;
public city: string = null;
public postalCode: string = null;
constructor() {
}
public save(transaction: any): void {
//save this.street via transaction (not important for this example)
//save this.city via transaction (not important for this example)
//save this.postalCode via transaction (not important for this example)
}
}
@Component({
selector: 'my-app',
providers: [],
template: `
<div>
<h2>Carousel/Wizzard like state maintaining navigation</h2>
<table style="width: 100%">
<tr>
<td style="text-align: left"><button (click)="prevBtnClick()">< Back</button></td>
<td style="text-align: right"><button (click)="nextBtnClick()">Next ></button></td>
</tr>
<tr>
<td colspan="2" style="text-align: center" #content>
<!-- here goes the content -->
<p *ngIf="ci < 0">No content loaded</p>
</td>
</tr>
</table>
</div>
`,
directives: []
})
export class App implements AfterViewInit {
@ViewChild('content', {read: ViewContainerRef}) content: ViewContainerRef;
private ci = -1;
private views = [];
constructor() {
this.loadViews();
if(this.views.length > 0) {
this.ci = 0;
}
}
public ngAfterViewInit(): void {
this.showView(this.ci);
}
//THIS IS THE KEY PART Nr. 1
public loadViews(): void { //this is simplyfied, in my case this is happening via a config loader which returns an array of "INITIALIZED" views
//i know that this does not work! It is just to get the idea:
var v = new UserForm();
v.uname = "Some initialized value";
v.passwd = "Usually loaded by another instance";
this.views.push(v);
v = new AddressForm();
v.street = "Examplestreet 15";
v.city = "Exampletown";
v.postalCode = "12345";
this.views.push(v);
}
protected prevBtnClick(): void {
if(this.ci < 0)
return;
this.ci++;
if(this.ci >= this.views.length)
this.ci = 0;
this.showView(this.ci);
}
protected nextBtnClick(): void {
if(this.ci < 0)
return;
this.ci--;
if(this.ci < 0)
this.ci = this.views.length - 1;
this.showView(this.ci);
}
//THIS IS THE KEY PART Nr. 2
public showView(index: number): void {
if(index < 0 || index >= this.views.length || !this.views || this.views.length == 0)
return;
this.ci = index;
var view = this.views[index];
//TODO: remove the currently loaded view from this.content
//TODO: load the view instance in this.content without creating a new instance
// because the state of the instance must be maintained!!
}
//not important for this example
public save(transaction: any): void {
for(var v of this.views)
(<Storable><any>v).save(transaction);
}
}