Angular MatTable 不更新来自表单的数据
Angular MatTable does not update with data that comes from a Form
刚开始学习Angular(其实是几个月前开始学习web开发的)。我想将表单中的数据显示到 table 中。我有以下型号:
export class Content {
id: number = 0;
title?: string;
subtitle?: string;
content?: string;
date?: string;
media?: string;
}
然后,我有一个表单,其中包含一些方法 onSubmit()
,可将数据推送到数组中。
onSubmit() {
if (this.selectedContent.id === 0) {
this.selectedContent.id = this.contentsList.length + 1;
this.contentsList.push(this.selectedContent);
}
this.selectedContent = new Content();
this.notificationService.success('El postulante se creó correctamente');
console.log(this.contentsList);
}
当我 console.log contentsList
它显示了表单中的新数据,但它没有显示在 table:
dataSource = this.contentsList;
columnsToDisplay = ['title', 'subtitle', 'body', 'date'];
expandedElement: Content | null | undefined;
这是我的 table:
<table mat-table [dataSource]="dataSource" multiTemplateDataRows class="mat-elevation-z8">
<ng-container matColumnDef="{{column}}" *ngFor="let column of columnsToDisplay">
<th mat-header-cell *matHeaderCellDef> {{column}} </th>
<td mat-cell *matCellDef="let content"> {{content[column]}} </td>
</ng-container>
<!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->
<ng-container matColumnDef="expandedDetail">
<td mat-cell *matCellDef="let element[attr.colspan]="columnsToDisplay.length">
<div class="example-element-detail" [@detailExpand]="element == expandedElement ? 'expanded' : 'collapsed'">
<div class="example-element-diagram">
<div class="example-element-position"> {{content.title}} </div>
<div class="example-element-symbol"> {{content.subtitle}} </div>
<div class="example-element-name"> {{content.date}} </div>
<div class="example-element-weight"> {{content.body}} </div>
</div>
<div class="example-element-description">
{{content.body}}
<span class="example-element-description-attribution"> </span>
</div>
</div>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
<tr mat-row *matRowDef="let content; columns: columnsToDisplay;"
class="example-element-row" [class.example-expanded-row]="expandedElement === content" (click)="expandedElement = expandedElement === content ? null : content">
</tr>
<tr mat-row *matRowDef="let row; columns: ['expandedDetail']" class="example-detail-row"></tr>
</table>
可能是您在组件中使用了 changeDetection
方法。
如果你有 ChangeDetectionStrategy
,请查看你的 ts 文件
这是示例代码。
@Component({
selector: 'test',
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './test.component.html',
styleUrls: ['test.component.scss'],
})
如果您有更改检测,则有两种方法可以解决此问题。
只需从您的组件 ts 文件中删除以下行。
changeDetection: ChangeDetectionStrategy.OnPush
请将以下代码添加到您的 ts 组件文件中。
在 ts 文件的顶部导入 ChangeDetectorRef。
import { ChangeDetectorRef } from '@angular/core';
添加对构造函数的引用。
constructor(public changeDetectorRef: ChangeDetectorRef) { }
在 onSubmit
方法末尾的行下方添加。
this.changeDetectorRef.detectChanges();
没有关于 changeDetectorRef 的信息。 MatTable 的问题是,如果我们 add/remove/change 数据源的一个元素,我们需要说再次重绘 table 请参阅文档,在 API about DataSource
If a data array is provided, the table must be notified when the array's objects are added, removed, or moved. This can be done by calling the renderRows() function which will render the diff since the last table render. If the data array reference is changed, the table will automatically trigger an update to the rows
因此,如果您的组件中只有一个 table,您可以使用 ViewChild 获取 table
@ViewChild(MatTable) table:MatTable<any>
因此,添加元素时使用 this.table.renderRows()
。
if (this.selectedContent.id === 0) {
...
this.table.renderRows()
}
但是您需要在代码中考虑另一件事。你用
//the code is WRONG
if (this.selectedContent.id === 0) {
this.contentsList.push(this.selectedContent);
}
this.selectedContent = new Content();
是错误的,因为您要添加相同的“对象”,您需要制作该对象的“副本”。如果你的对象是一个简单的对象,这个副本可以使用 spreadOperator 来制作,所以函数最终变成了
onSubmit() {
if (this.selectedContent.id === 0) {
this.selectedContent.id = this.contentsList.length + 1;
//push a "copy of the object
this.contentsList.push({...this.selectedContent});
this.table.renderRows()
}
this.selectedContent = new Content();
}
刚开始学习Angular(其实是几个月前开始学习web开发的)。我想将表单中的数据显示到 table 中。我有以下型号:
export class Content {
id: number = 0;
title?: string;
subtitle?: string;
content?: string;
date?: string;
media?: string;
}
然后,我有一个表单,其中包含一些方法 onSubmit()
,可将数据推送到数组中。
onSubmit() {
if (this.selectedContent.id === 0) {
this.selectedContent.id = this.contentsList.length + 1;
this.contentsList.push(this.selectedContent);
}
this.selectedContent = new Content();
this.notificationService.success('El postulante se creó correctamente');
console.log(this.contentsList);
}
当我 console.log contentsList
它显示了表单中的新数据,但它没有显示在 table:
dataSource = this.contentsList;
columnsToDisplay = ['title', 'subtitle', 'body', 'date'];
expandedElement: Content | null | undefined;
这是我的 table:
<table mat-table [dataSource]="dataSource" multiTemplateDataRows class="mat-elevation-z8">
<ng-container matColumnDef="{{column}}" *ngFor="let column of columnsToDisplay">
<th mat-header-cell *matHeaderCellDef> {{column}} </th>
<td mat-cell *matCellDef="let content"> {{content[column]}} </td>
</ng-container>
<!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->
<ng-container matColumnDef="expandedDetail">
<td mat-cell *matCellDef="let element[attr.colspan]="columnsToDisplay.length">
<div class="example-element-detail" [@detailExpand]="element == expandedElement ? 'expanded' : 'collapsed'">
<div class="example-element-diagram">
<div class="example-element-position"> {{content.title}} </div>
<div class="example-element-symbol"> {{content.subtitle}} </div>
<div class="example-element-name"> {{content.date}} </div>
<div class="example-element-weight"> {{content.body}} </div>
</div>
<div class="example-element-description">
{{content.body}}
<span class="example-element-description-attribution"> </span>
</div>
</div>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
<tr mat-row *matRowDef="let content; columns: columnsToDisplay;"
class="example-element-row" [class.example-expanded-row]="expandedElement === content" (click)="expandedElement = expandedElement === content ? null : content">
</tr>
<tr mat-row *matRowDef="let row; columns: ['expandedDetail']" class="example-detail-row"></tr>
</table>
可能是您在组件中使用了 changeDetection
方法。
如果你有 ChangeDetectionStrategy
,请查看你的 ts 文件
这是示例代码。
@Component({
selector: 'test',
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './test.component.html',
styleUrls: ['test.component.scss'],
})
如果您有更改检测,则有两种方法可以解决此问题。
只需从您的组件 ts 文件中删除以下行。
changeDetection: ChangeDetectionStrategy.OnPush
请将以下代码添加到您的 ts 组件文件中。
在 ts 文件的顶部导入 ChangeDetectorRef。
import { ChangeDetectorRef } from '@angular/core';
添加对构造函数的引用。
constructor(public changeDetectorRef: ChangeDetectorRef) { }
在 onSubmit
方法末尾的行下方添加。
this.changeDetectorRef.detectChanges();
没有关于 changeDetectorRef 的信息。 MatTable 的问题是,如果我们 add/remove/change 数据源的一个元素,我们需要说再次重绘 table 请参阅文档,在 API about DataSource
If a data array is provided, the table must be notified when the array's objects are added, removed, or moved. This can be done by calling the renderRows() function which will render the diff since the last table render. If the data array reference is changed, the table will automatically trigger an update to the rows
因此,如果您的组件中只有一个 table,您可以使用 ViewChild 获取 table
@ViewChild(MatTable) table:MatTable<any>
因此,添加元素时使用 this.table.renderRows()
。
if (this.selectedContent.id === 0) {
...
this.table.renderRows()
}
但是您需要在代码中考虑另一件事。你用
//the code is WRONG
if (this.selectedContent.id === 0) {
this.contentsList.push(this.selectedContent);
}
this.selectedContent = new Content();
是错误的,因为您要添加相同的“对象”,您需要制作该对象的“副本”。如果你的对象是一个简单的对象,这个副本可以使用 spreadOperator 来制作,所以函数最终变成了
onSubmit() {
if (this.selectedContent.id === 0) {
this.selectedContent.id = this.contentsList.length + 1;
//push a "copy of the object
this.contentsList.push({...this.selectedContent});
this.table.renderRows()
}
this.selectedContent = new Content();
}