角+材料 - 如何刷新数据源(MAT -Table)
我正在使用 mat-table 列出用户选择的语言的内容。他们还可以使用对话面板添加新语言。他们添加了一种语言并返回。我希望我的数据源刷新以显示它们所做的更改。
我通过从服务中获取用户数据并将其传递到刷新方法中的数据源中来初始化数据存储。
language.component.ts
import { Component, OnInit } from '@angular/core';
import { LanguageModel, LANGUAGE_DATA } from '../../../../models/language.model';
import { LanguageAddComponent } from './language-add/language-add.component';
import { AuthService } from '../../../../services/auth.service';
import { LanguageDataSource } from './language-data-source';
import { LevelbarComponent } from '../../../../directives/levelbar/levelbar.component';
import { DataSource } from '@angular/cdk/collections';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import { MatSnackBar, MatDialog } from '@angular/material';
@Component({
selector: 'app-language',
templateUrl: './language.component.html',
styleUrls: ['./language.component.scss']
})
export class LanguageComponent implements OnInit {
displayedColumns = ['name', 'native', 'code', 'level'];
teachDS: any;
user: any;
constructor(private authService: AuthService, private dialog: MatDialog) { }
ngOnInit() {
this.refresh();
}
add() {
this.dialog.open(LanguageAddComponent, {
data: { user: this.user },
}).afterClosed().subscribe(result => {
this.refresh();
});
}
refresh() {
this.authService.getAuthenticatedUser().subscribe((res) => {
this.user = res;
this.teachDS = new LanguageDataSource(this.user.profile.languages.teach);
});
}
}
language-data-source.ts
import {MatPaginator, MatSort} from '@angular/material';
import {DataSource} from '@angular/cdk/collections';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/observable/merge';
import 'rxjs/add/operator/map';
export class LanguageDataSource extends DataSource<any> {
constructor(private languages) {
super();
}
connect(): Observable<any> {
return Observable.of(this.languages);
}
disconnect() {
// No-op
}
}
因此,我试图调用一种刷新方法,在该方法中,我再次从后端获得用户,然后我重新开始数据来源。但是,这不起作用,没有发生任何变化。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(28)
我不知道在创建问题时是否需要
更改eTectorRef
,但是现在这已经足够了:示例:
stackblitz
I don't know if the
ChangeDetectorRef
was required when the question was created, but now this is enough:Example:
StackBlitz
通过使用
consewetectorRef
)方法收到新数据后,注入 changeTectorRef 在构造函数中并使用检测案例这样:
Trigger a change detection by using
ChangeDetectorRef
in therefresh()
methodjust after receiving the new data, inject ChangeDetectorRef in the constructor and use detectChanges like this:
因此,对我而言,没有人能为我遇到的问题提供好的答案,而我遇到的问题几乎是@kay。对我来说,这是关于排序的,排序表不会发生在垫子中。
我目的是这个答案,因为这是我通过搜索Google找到的唯一主题。
我正在使用Angular 6。
如所说在这里:
因此,您只需要在 refresh()方法中调用 renderrows()即可出现更改。
请参阅在这里进行集成。
So for me, nobody gave the good answer to the problem that i met which is almost the same than @Kay. For me it's about sorting, sorting table does not occur changes in the mat.
I purpose this answer since it's the only topic that i find by searching google.
I'm using Angular 6.
As said here:
So you just have to call renderRows() in your refresh() method to make your changes appears.
See here for integration.
在Angular 9中,秘密是
this.datasource.data = this.datasource.data;
示例:
In Angular 9, the secret is
this.dataSource.data = this.dataSource.data;
Example:
由于您正在使用
matpaginator
,您只需要做任何事情更改为Paginator,此触发数据重新加载。简单的技巧:
这将页面大小更新为当前页面大小,因此基本上没有任何变化,除了私有
_EmitPageEvent()
函数也被调用,触发表重新加载。Since you are using
MatPaginator
, you just need to do any change to paginator, this triggers data reload.Simple trick:
This updates the page size to the current page size, so basically nothing changes, except the private
_emitPageEvent()
function is called too, triggeing table reload.添加了新的数据行后,我通过更新数据源而无需使用其实例来刷新材料表。
html中的表:
component.ts 中的adduser():
After adding a new data row, I refreshed my material table by updating dataSource without using its instance.
Table in HTML:
addUser() in file component.ts:
使用DataSource Connect函数
您可以像这样 。 “数据”是数据表的新值
You can just use the datasource connect function
like so. 'data' being the new values for the datatable
在您的添加或删除特定行的操作下方添加此行。
Add this line below your action of add or delete the particular row.
您还可以使用renderrows()方法:
然后
进行参考,请查看: Angular 10 | 9 | 8编辑/添加/添加/ delete行在材料表中使用对话框内联行动
You can also use the renderRows() method:
then
For reference, check this out: Angular 10|9|8 Edit/ Add/ Delete Rows in Material Table with using Dialogs inline Row Operation
好吧,我遇到了一个类似的问题,我在数据源中添加了一些东西,但它没有重新加载。
我发现的最简单方法只是重新分配数据:
Well, I ran into a similar problem where I added something to the data source, and it's not reloading.
The easiest way I found was simply to reassign the data:
做到这一点的最佳方法是在您的数据源实现中添加可观察到的其他可观察到的方法。
在连接方法中,您应该已经使用
observable.merge
订阅包括Paginator.paginator.page,sort.SortChange等的一系列可观察到的物品。当您需要引起刷新时。这样的事情:
然后您可以调用
recordChange $ .next()
启动刷新。自然,我会用refresh()方法包装调用,并将其从组件中的数据源实例和其他适当的技术中调用。
Best way to do this is by adding an additional observable to your Datasource implementation.
In the connect method you should already be using
Observable.merge
to subscribe to an array of observables that include the paginator.page, sort.sortChange, etc. You can add a new subject to this and call next on it when you need to cause a refresh.something like this:
And then you can call
recordChange$.next()
to initiate a refresh.Naturally I would wrap the call in a refresh() method and call it off of the datasource instance w/in the component, and other proper techniques.
有两种方法可以做到这一点,因为角质材料不一致,并且记录在很差的情况下。当新行到达时,Angular材料表将不会更新。令人惊讶的是,有人告诉这是因为性能问题。但是它看起来更像是一个辅助问题,他们无法更改它。当新行发生时,应该可以预期该表可以更新。如果默认情况下不应启用此行为,则应有一个开关将其关闭。
无论如何,我们无法改变角度的材料。但是,我们基本上可以使用非常差的方法来执行此操作:
- 如果您直接将数组用作源:
table是MAT -TABL
一个 排序和其他功能
table.renderrows()令人惊讶地无法使用。因为Mat-Table在这里不一致。您需要使用hack来告诉源更改。您可以使用此方法进行操作:
DataSource是用于分类和其他功能的Mattabledatasource包装器。
There are two ways to do it, because Angular Material is inconsistent, and this is very poorly documented. Angular material table won't update when a new row will arrive. Surprisingly, it is told it is because of performance issues. But it looks more like a by-design issue, and they can not change it. It should be expected for the table to update when a new row occurs. If this behavior should not be enabled by default, there should be a switch to switch it off.
Anyway, we can not change Angular Material. But we can basically use a very poorly documented method to do it:
One - if you use an array directly as a source:
where table is ViewChild of the mat-table
Second - if you use sorting and other features
table.renderRows() surprisingly won't work. Because mat-table is inconsistent here. You need to use a hack to tell the source changed. You do it with this method:
where dataSource is MatTableDataSource wrapper used for sorting and other features.
我使用两个资源实现了一个很好的解决方案:
刷新数据源和吊架:
例如,在此处定义 dataSource :
I achieved a good solution using two resources:
refreshing both dataSource and paginator:
where for example dataSource is defined here:
我已经尝试了一些以前的建议。它确实更新了表,但是我有一些疑问:
更新
dataSource.data
及其克隆。例如如果数据很大,则将重新分配大量内存。此外,MaTable认为桌子内部的一切都是新的,因此可能会导致性能问题。我找到了我的桌子闪烁,我的桌子有大约300行。
调用
paginator._changepagesize
。例如它将发射
页面
事件。如果您已经对page
事件进行了一些处理。您可能会发现这很奇怪,因为该事件可能会多次发射。而且可能会有风险,如果某种情况将事件触发_changePagesize()
间接地导致无限循环...我在这里建议另一种解决方案。如果您的表不依赖
dataSource
'sfilter
field。您可以更新
过滤器
字段触发表刷新:这样做,表将执行过滤并因此更新表的UI。但是它需要您自己的
datasource.filterpredicate()
才能处理过滤逻辑。I have tried some of the previous suggestions. It does update the table, but I have some concerns:
Updating
dataSource.data
with its clone. e.g.If the data is large, this will reallocate lot of memory. Moreover, MatTable thinks that everything is new inside the table, so it may cause performance issue. I found my table flickers where my table has about 300 rows.
Calling
paginator._changePageSize
. e.g.It will emit
page
event. If you have already had some handling for thepage
event. You may find it weird because the event may be fired more than once. And there can be a risk that if somehow the event will trigger_changePageSize()
indirectly, it will cause infinite loop...I suggest another solution here. If your table is not relying on
dataSource
'sfilter
field.You may update the
filter
field to trigger table refresh:By doing so, the table will perform filtering and thus updating the UI of the table. But it requires having your own
dataSource.filterPredicate()
to handling your filtering logic.我曾尝试过更换eTectorRef,主题和行为对象,但这对我有用:
I had tried ChangeDetectorRef, Subject and BehaviourSubject, but this works for me:
您可以使用“ Concat”轻松更新表的数据:
例如:
Leganagency.component.ts
Lagans.component.html
,当您更新数据(Leganagenage.component.ts)时:
使用“ Concat”时Angular检测对象的更改(this.teachds),您无需使用另一件事。
PD:在Angular 6和7中对我来说是工作的,我没有尝试其他版本。
You can easily update the data of the table using "concat":
for example:
language.component.ts
language.component.html
And, when you update the data (language.component.ts):
When you're using "concat" angular detect the changes of the object (this.teachDS) and you don't need to use another thing.
PD: It's work for me in angular 6 and 7, I didn't try another version.
在Angular 10中,这对我有用:
在HTML中:
在打字稿组件中:
In Angular 10, this is what works for me:
In the HTML:
In the TypeScript component:
这对我有用:
This worked for me:
在我的情况下(Angular 6+),我从
mattabledatasource
创建mydatasource
。 之后this.data = somearray
数据未显示
class mydatasource
in my case (Angular 6+), I inherited from
MatTableDataSource
to createMyDataSource
. Without calling afterthis.data = someArray
data where not displayed
class MyDataSource
我认为
mattabledatasource
对象与您传递给mattabledataSource
构造函数的数据数组链接到某种方式。例如:
因此,当您必须更改数据时;在原始列表上更改
dataTable
,然后通过call_UPDATECHANGESUBSCRIPEND()
方法tables
反映表上的更改。例如:
通过Angular 6与我一起工作。
I think the
MatTableDataSource
object is some way linked with the data array that you pass toMatTableDataSource
constructor.For instance:
So, when you have to change data; change on the original list
dataTable
and then reflect the change on the table by call_updateChangeSubscription()
method ontableDS
.For instance:
That's work with me through Angular 6.
这对我有用:
因此,您应该将数据量实例声明为
mattabledataSource
This is working for me:
So you should declare your datasource instance as
MatTableDataSource
我做了更多的研究,发现了这个地方可以给我我所需的东西 - 从服务器刷新时会感到干净,并且与更新数据有关:
https://blog.angular-university.io/angular-university.io/angular-martular-material-material-material-material-data - 表/
上面页面的大多数学分。以下是如何使用MAT-SELECTOR更新到选择的数据源的MAT-selector的示例。我正在使用Angular 7。对不起,很广泛,试图完整但简洁 - 我已经撕掉了尽可能多的不需要零件。希望能帮助别人进步更快!
akurys.model.ts:
andybom.service.ts:
agrismationDatasource.model.ts:
ashancomations.component.html:
ashancomations.component.component.scss:
andybor.com.component.ts:ts:
I did some more research and found this place to give me what I needed - feels clean and relates to update data when refreshed from server:
https://blog.angular-university.io/angular-material-data-table/
Most credits to the page above. Below is a sample of how a mat-selector can be used to update a mat-table bound to a datasource on change of selection. I am using Angular 7. Sorry for being extensive, trying to be complete but concise - I have ripped out as many non-needed parts as possible. With this hoping to help someone else getting forward faster!
organization.model.ts:
organization.service.ts:
organizationdatasource.model.ts:
organizations.component.html:
organizations.component.scss:
organization.component.ts:
阅读材料表不更新发布帖子数据更新#11638错误报告
我发现最好的(阅读,最简单的解决方案)是最终评论者“ Shhdharmen”所建议的,建议使用EventEmitter。
这涉及对生成的数据源类的一些简单更改,
即IE)在您的数据源类中添加一个新的私人变量
,以及我将新数据推向内部数组(this.data)的位置,我发出了一个事件。
最后,在“连接”方法中更改“数据卡”数组 - 如下
After reading Material Table not updating post data update #11638 Bug Report
I found the best (read, the easiest solution) was as suggested by the final commentor 'shhdharmen' with a suggestion to use an EventEmitter.
This involves a few simple changes to the generated datasource class
ie) add a new private variable to your datasource class
and where I push new data to the internal array (this.data), I emit an event.
and finally, change the 'dataMutation' array in the 'connect' method - as follows
在Angular 15中,以前的解决方案都不适合我。
相反,我必须使用
stackblitz示例示例。
In Angular 15, none of the previous solutions worked for me.
Instead, I had to use
See the StackBlitz example for an example.
当您设置 dataSource.ts 文件而不是使用简单数组进行数据时,请使用主题和Getter/setter进行数据:
然后在您的
connect()
中使用。函数使用dataStream主题这样:因此,现在,当您更改dataSource.data array ...像这样:
它会触发
this.datastream.next(v)
在setter和connect()功能将正确更新表。
可以在此处找到一个完整的工作示例:
When you set up your datasource.ts file instead of using a simple array for data, use a subject and getter/setter for data like so:
Then in your
connect()
function use the dataStream subject like so:So now when you change your dataSource.data array...like so:
it will trigger the
this.dataStream.next(v)
in the setter and theconnect()
function will update your table properly.A full working example can be found here:
https://stackblitz.com/edit/angular-material2-issue-yzhsml?file=app%2Fdata-table-datasource.ts
尝试一下。它可能会帮助您。
从加载用户的功能开始。
定义刷新功能,删除用户后将用于刷新表。
现在,您可以在删除用户流程后,可以调用RefResh()函数,如下所示。
Try this. It may help you.
Start with a function which loads users.
The define a refresh function, which will be used to refresh the table after deleting the user.
Now you can call the refresh() function after you finish deleting the user process, like below.