Angular2 DynamicComponentLoader,参数为

时间:2016-02-22 14:36:14

标签: angular

我正在尝试创建一个表组件,它将根据列描述和原始数据构建一个表。

我能够毫无问题地创建基本功能,但我还希望能够覆盖单个单元格的默认呈现,以便能够显示自定义内容(例如,显示链接)。

DataTables中使用的类似方式,唯一不同的是,我希望能够为带有参数的自定义组件传递名称。

我最初的尝试是这样的,但问题出现了,如果我在列的显示功能中实例化组件,我无法在页面上显示它。

@Component({
  selector: 'gt-table',
  template: `
  <table class="table table-striped table-hover">
    <thead>
      <tr>
        <th *ngFor="#column of columns">
          {{ column.title }}
        </th>
      </tr>
    </thead>
    <tbody>
      <tr *ngFor="#row of data">
        <td *ngFor="#column of columns">
          {{ displayCell(row, column) }}
        </td>
      </tr>
    </tbody>
  </table>
  `
  })
  export class GTTableComponent implements {
    @Input() data:Array<any>;
    @Input() columns:Array<any>;

  displayCell(row, column) {
    if (column.display !== undefined) {
      return column.display(row[column.name], row);
    } else {
      return row[column.name];
    }
  }
}

在互联网上搜索后,我发现为了在视图中动态加载组件,您需要使用DynamicComponentLoader

在经历了很多头痛和搜索之后,我能够在response找到与我正在寻找的东西类似的东西,尽管它不是最漂亮的。

剩下的唯一问题是如何传递参数?我无法找到关于使用参数动态加载组件的单一参考。任何帮助或建议?

解决方案:

因此,解决方案是将DynamicComponentLoaderloadIntoLocation函数一起使用。 loadAsRoot会更理想,但从2.0.0-beta.7状态来看,它是错误的,您无法从承诺中设置实例属性。

所以我所做的是为单元格创建一个组件,我决定是否需要实例化默认的显示组件或用户想要处理它:

import {Component, Input, OnInit, ElementRef, DynamicComponentLoader, 
ComponentRef} from 'angular2/core';

import {GTTableDefaultDisplayComponent} from './gt-tabledefaultdisplay.component';
@Component({
    selector: '[gt-cell]',
    template: `<div #content></div>`,
    directives: []
})
export class GTTableCellComponent implements OnInit {
  @Input() row:any;
  @Input() column:any;

  constructor(private _loader: DynamicComponentLoader, private _elementRef: ElementRef) {
  }

  ngOnInit() {
    if (this.column.display !== undefined) {
      this.column.display(this._loader, this._elementRef, 'content',
      this.row[this.column.name],this.row);
    } else {
      this._loader.loadIntoLocation(GTTableDefaultDisplayComponent,
      this._elementRef, 'content').then((compRef:ComponentRef) => {
        compRef.instance['content'] = this.row[this.column.name];
      });
    }
  }
}

因此,使用属性加载动态组件的方法是在使用compRef:ComponentRef返回的promise中设置它。这将是一个变量,您可以使用compRef.instance访问新创建的组件的实例,并将其用作数组来设置其变量。

我的默认视图组件就像这样简单:     从'angular2 / core'导入{Component,Input};

import {GTTableLinkComponent} from './gt-tablelink.component';

@Component({
    selector: 'default-display',
    template: `<div>{{content}}</div>`,
    directives: []
})
export class GTTableDefaultDisplayComponent {
  @Input() content:string;

  constructor() {
  }
}

我希望这对其他人也有帮助。

3 个答案:

答案 0 :(得分:10)

您可以使用loadAsRoot(或loadNextToLocationloadIntoLocation)方法返回的承诺来访问新组件实例并在其上设置元素:

dcl.loadAsRoot(ChildComponent, '#child',
   injector).then((compRef:ComponentRef) => {

  // For example
  compRef.param1 = 'something';

  // In your case
  compRef.data = [
    { ... },
    { ... },
    { ... }
  ];
  compRef.columns = [
    'column1', 'column2'
  ];

});

答案 1 :(得分:4)

DynamicComponentLoader的方法返回Promise<ComponentRef> s。

Promise<ComponentRef>中的ComponentRef有一个instance字段。用它来改变你新创建的组件的属性。

演示(经过测试的@ 2.0.0-rc.4;适用于更高版本)

import { Component, DynamicComponentLoader,  ViewContainerRef,
                                                         ViewChild } from '@angular/core';
import { bootstrap } from '@angular/platform-browser-dynamic';

@Component({
  selector: 'loaded-with-var-component',
  template: '~~LOADED COMPONENT WITH VAR: {{ varValue }}~~'
})
class LodadedWithVarComponent {
  varValue: String = "defaultVarValue";
}


@Component({
  selector: 'my-app',
  template: '(<span #myVar></span>)<br>Parent'
})
class MyApp {

  @ViewChild('myVar', {read: ViewContainerRef}) myVar:ViewContainerRef;

  constructor(private dcl: DynamicComponentLoader) {
  }

  ngAfterViewInit() {
    this.dcl.loadNextToLocation(LodadedWithVarComponent, this.myVar)
      .then((c:ComponentRef) => {
        c.instance.varValue = 'changed-var-value';  // <-- This is where the magic happens!
      });
  }
}
bootstrap(MyApp);

就是这样!

旧:使用angular2-beta.15及以下

的上一个演示
import {DynamicComponentLoader, ElementRef, Component, Input, View} from 'angular2/core';
import {bootstrap}    from 'angular2/platform/browser';

@Component({
  selector: 'child-component',
  template: 'Child {{ stuff }}'
})
class ChildComponent {
    stuff: String = "defaultValue";
}

@Component({
  selector: 'my-app',
  template: 'Parent (<div #child></div>)'
})
class MyApp {
  constructor(private dcl: DynamicComponentLoader, private elementRef: ElementRef) {
  }
  ngOnInit() {
    this.dcl.loadIntoLocation(ChildComponent, this.elementRef, 'child')
      .then((c:ComponentRef) => {
         c.instance.stuff = 'something'; // <------------ This is where the magic happens!
      });
  }
}

bootstrap(MyApp);

答案 2 :(得分:0)

使用属性指令。

属性指令最低限度地要求构建一个使用指令装饰器注释的控制器类。指令装饰器指定标识与指令关联的属性的选择器。控制器类实现了所需的指令行为。

<td [column]="column">...</td>