没有setTimeOut,MatSort和MatPaginator不起作用 [英] MatSort and MatPaginator does not work without setTimeOut

查看:143
本文介绍了没有setTimeOut,MatSort和MatPaginator不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有来自端点的数据并将其放入MatTableDataSource。我能够让它适用于MatSort和MatPaginator,但需要使用setTimeOut,这似乎不是一个正确的方法来做到这一点。如果我删除它,它会抱怨'无法读取sort undefined的属性',我认为这是由于它尚未初始化。

I have a data coming from an endpoint and put it into MatTableDataSource. I was able to get it working for MatSort and MatPaginator, but needed to use setTimeOut, which does not seems to be a proper way to do this. If I remove this, it will complain that 'Can not read property of sort undefined' which I assumed this is due to it's not initialized yet.

我也尝试过:


  • 将其移动到afterviewinit,但数据是在
    之后加载的,因为它被调用后仍然无效

  • 在this.datasource =
    new之后使用this.changeDetectorRef.detectChanges()...也不起作用

这是我当前的代码(工作正常但是使用settimeout)

This is my current code (which is working, but using settimeout)

<div *ngIf="!isLoading">
    <div *ngFor="let record of renderedData | async" matSort>

    // ... some html to show the 'record'

    <mat-paginator #paginator
        [pageSizeOptions]="[5, 10, 20]">
    </mat-paginator>
</div>

组件

export class ResultsComponent implements OnInit, OnDestroy, AfterViewInit {
    dataSource: MatTableDataSource<any> = new MatTableDataSource();
    renderedData: Observable<any>;

    @ViewChild(MatPaginator) paginator: MatPaginator;
    @ViewChild(MatSort) sort: MatSort;

    constructor(some service) {}

    ngOnInit() {
        const accountId = someOtherService.getAccountId();
        this.someService.getData(accountId)
            .subscribe((myData) => {
                    this.dataSource = new MatTableDataSource(myData);

                    // it won't work properly if it is not wrapped in timeout
                    setTimeout(() => {
                        this.dataSource.paginator = this.paginator;
                        this.sort.sort(<MatSortable>({id: 'created_on', start: 'desc'}));
                        this.dataSource.sort = this.sort;
                    });

                    this.renderedData = this.dataSource.connect();
                }
            });
    }

    ngAfterViewInit() {
    }

    ngOnDestroy(): void {
        if (this.dataSource) { this.dataSource.disconnect(); }
    }
}

以上代码对我有用,我如果可能的话,我只是想以正确的方式不使用settimeout。

The above code is working for me, I'm just looking the right way not to use settimeout if possible.

推荐答案

这里有几个生命周期时间问题,当你想到它时,这是对的。

There are a couple of lifecycle timing issues at play here, and when you think about it, this is right.

MatSort是视图的一部分,因此在OnInit期间它没有准备好 - 它是未定义的。因此尝试使用它会引发错误。

The MatSort is part of the view, so it isn't 'ready' during OnInit - it is undefined. So trying to use it throws the error.

MatSort在AfterViewInit中已经准备就绪,但由于您需要将应用排序到执行排序后的数据源,这将通过连接到数据源的renderedData触发对视图的更改。因此,您最终会得到一个ExpressionChangedAfterItHasBeenCheckedError,因为视图初始化生命周期尚未完成,但您已经在尝试更改它。

The MatSort is ready in AfterViewInit, but things are further complicated by the fact that you need to 'apply' the sort to the datasource after performing the sort, and this triggers changes to the view by way of the renderedData that is 'connected' to the datasource. You therefore end up with an ExpressionChangedAfterItHasBeenCheckedError because the view initialization lifecycle hasn't completed but you are already trying to change it.

因此您无法排序直到视图为止准备就绪,当您收到视图已准备好的通知时,您无法应用排序。您唯一能做的就是等到组件初始化生命周期结束。你可以使用setTimeout()来做到这一点。

So you can't sort until the view is ready, and you can't apply the sort when you are notified that the view is ready. The only thing you can do is wait until the end of the component initialization lifecycle. And you can do that using setTimeout().

我不认为没有setTimeout()可以解决这两个问题,所以在这种情况下它不会无论你是从OnInit还是AfterViewInit调用它。

I don't think there is any way around both of these problems without setTimeout(), so in that case it doesn't matter whether you call it from OnInit or AfterViewInit.

关于你的代码的其他一些观察结果:

A couple of other observations on your code:

您无需在订阅中创建MatTableDataSource的新实例。您可以将结果数据分配给已创建的数据源:

You don't need to create a new instance of MatTableDataSource in your subscription. You can assign the result data to the already created datasource:

this.dataSource.data = myData;

这使你不必在以后将渲染数据连接到数据源,这样你就可以做到初始化数据源时:

This frees you up from having to connect the rendered data to the datasource afterward, so you can do it when you initialize the datasource:

dataSource: MatTableDataSource<any> = new MatTableDataSource();
renderedData: Observable<any> = this.dataSource.connect();

这篇关于没有setTimeOut,MatSort和MatPaginator不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆