我正在尝试创建一个表组件,它将根据列描述和原始数据构建一个表。
我能够毫无问题地创建基本功能,但我还希望能够覆盖单个单元格的默认呈现,以便能够显示自定义内容(例如,显示链接)。
以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找到与我正在寻找的东西类似的东西,尽管它不是最漂亮的。
剩下的唯一问题是如何传递参数?我无法找到关于使用参数动态加载组件的单一参考。任何帮助或建议?
解决方案:
因此,解决方案是将DynamicComponentLoader
与loadIntoLocation
函数一起使用。 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() {
}
}
我希望这对其他人也有帮助。
答案 0 :(得分:10)
您可以使用loadAsRoot
(或loadNextToLocation
或loadIntoLocation
)方法返回的承诺来访问新组件实例并在其上设置元素:
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
字段。用它来改变你新创建的组件的属性。
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);
就是这样!
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>