Angular2:创建组件实例而不注入它

Angular2:创建组件实例而不注入它,angular,components,Angular,Components,问题 Angular2中有没有一种方法可以创建组件的实例而不实际注入它?使用ViewContainerRef.insert()或其他类似工具将组件插入到视图中 我知道有DynamicComponentLoader,但它需要一个ViewContainerRef来附加它自己创建的实例。该视图当时甚至不存在 问题是,我想创建视图实例,配置它们(甚至通过自定义工厂),并在其他点将它们添加到任何视图中 有一个ViewContainerRef,它能够在任意索引处插入ViewRef,这到目前为止还不错,但是如

问题

Angular2中有没有一种方法可以创建组件的实例而不实际注入它?使用ViewContainerRef.insert()或其他类似工具将组件插入到视图中

我知道有DynamicComponentLoader,但它需要一个ViewContainerRef来附加它自己创建的实例。该视图当时甚至不存在

问题是,我想创建视图实例,配置它们(甚至通过自定义工厂),并在其他点将它们添加到任何视图中

有一个ViewContainerRef,它能够在任意索引处插入ViewRef,这到目前为止还不错,但是如何从我创建的组件创建ViewRef而不实际插入它呢

我希望你明白我的问题:p

更新:

一个示例应用程序是通过表单的类似旋转木马的导航。应该创建视图,并且只有具有当前索引的视图才应该加载之前的状态

下面是一个未完成的示例,其中包含一些标记关键位置的TODO(请参见LoadView()和showView(),以了解相关信息)

从'@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()">&lt; Back</button></td>
          <td style="text-align: right"><button (click)="nextBtnClick()">Next &gt;</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);
  }
}