我正在尝试创建一个角度组件,它使用提供的对象数组呈现html表。
我已实施OnChanges
来检测对@Input
的更改,但它似乎无效。
为了测试,我使用setInterval
添加一些数据,但它没有反映在子组件中。
这是我到目前为止的代码,
NG-table.component.ts:
export class NgTableComponent implements OnInit, OnChanges {
@Input() data: any[];
private columns: string[];
private rows: string[][];
constructor() {
this.columns = [];
this.rows = [];
}
ngOnInit() {
}
ngOnChanges(changes: SimpleChanges) {
console.log(changes);
if (changes.data) {
this.extractRowsAndColumns(this.data);
}
}
extractRowsAndColumns(objArray: any[]): void {
const colSet = new Set<string>();
for (let i = 0; i < objArray.length; i++) {
const keys = Object.keys(objArray[i]);
for (let j = 0; j < keys.length; j++) {
colSet.add(keys[j]);
}
}
this.columns = Array.from(colSet);
for (let i = 0; i < objArray.length; i++) {
const obj = objArray[i];
const row = [];
for (let j = 0; j < this.columns.length; j++) {
if (obj.hasOwnProperty(this.columns[j])) {
row.push(obj[this.columns[j]]);
} else {
row.push(null);
}
}
this.rows.push(row);
}
}
}
NG-table.component.html:
<div>
<table class="ngtable">
<tr>
<th *ngFor="let col of columns">
{{col}}
</th>
</tr>
<tr *ngFor="let row of rows">
<td *ngFor="let cell of row">{{cell}}</td>
</tr>
</table>
</div>
我在app.component
中使用上面的组件app.component.ts:
export class AppComponent {
timer: any;
count = 0;
constructor() {
const o: any = {
'id': 1,
'name': 'Jeanette',
'last_name': 'Penddreth',
'email': 'jpenddreth0@census.gov',
'gender': 'Female',
'ip_address': '26.58.193.2'
};
this.timer = setInterval(() => {
this.data.push(o);
console.log(this.data.length);
if ( this.count++ === 5) {
clearInterval(this.timer);
}
}, 1000 * 1);
}
data = [{
'id': 1,
'name': 'Jeanette',
'last_name': 'Penddreth',
'email': 'jpenddreth0@census.gov',
'gender': 'Female',
'ip_address': '26.58.193.2'
}, {
'id': 2,
'name': 'Giavani',
'last_name': 'Frediani',
'email': 'gfrediani1@senate.gov',
'gender': 'Male',
'ip_address': '229.179.4.212'
}, {
'id': 3,
'name': 'Noell',
'last_name': 'Bea',
'email': 'nbea2@imageshack.us',
'gender': 'Female',
'ip_address': '180.66.162.255'
}, {
'id': 4,
'name': 'Willard',
'last_name': 'Valek',
'email': 'wvalek3@vk.com',
'gender': 'Male',
'ip_address': '67.76.188.26'
}];
}
app.component.html:
<app-ng-table [data]="data"></app-ng-table>
如何在@Input
更改时更新组件?
更新:我创建了一个plunkr来证明这一点:https://plnkr.co/edit/szz1SNooQ1vIZhnFgiys?p=preview
答案 0 :(得分:2)
作为问题的简单解决方案,您可以检测@Input
中的ngOnChanges
更改,如下所示:
ngOnChanges(changes: SimpleChanges) {
for (let propName in changes) {
// when your @Input value is changed
if(propName === "yourInputName"){
// update the component here
}
}
}
希望有所帮助:)
答案 1 :(得分:2)
只需进行@Input()双向绑定......
_data;
@Input() set data(val) {
this._data = val;
}
get data() {
return this._data;
}
答案 2 :(得分:1)
之前我遇到过同样的问题; ngOnChanges
方法仅侦听数据类型==!
数组的更改。
解释(ngOnChanges not firing for nested object):
在更改检测期间,当Angular检查组件的输入时 更改属性,它使用(基本上)===进行脏检查。 对于数组,这意味着对数组引用(仅)进行脏检查。 由于rawLapsData数组引用没有改变,ngOnChanges() 将不会被召唤。
答案 3 :(得分:0)
正如TimHovius所说,angular只是在进行参考检查。由于您要推送到同一个数组,因此ng-table.component未检测到更改(对输入的引用仍然相同)。您可以做的一件事是创建数组的浅表副本。
addItem(): void {
this.data.push(this.data[this.data.length-1]);
// create shallow copy of array, since this is a new array (and new reference) ngOnChanges hook of the ng-table.component will fire
this.data = this.data.slice(0);
}
现在ng-table.component将检测到输入已更改并触发ngOnChanges
这是一个演示此(https://plnkr.co/edit/2tdMEA9PLc2TEL4Gy4Lp?p=preview)
的plunkr答案 4 :(得分:0)
您需要为其分配新对象。大部分都可以通过Object.assign
在你的例子中,你只需要改变几行,休息就可以顺利进行。
...
let data:[] = this.data;
data.push(o);
this.data = Object.assign([], data);
...