【发布时间】:2021-07-15 23:08:05
【问题描述】:
我正在尝试使用 Angular Material 表来列出我使用 websocket 从后端服务器获得的一些信息,但它仅在我单击显示的列进行排序时才显示元素,而不是在初始加载时显示,
这是我的数据表组件代码:
import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTable } from '@angular/material/table';
import { observable, of as observableOf } from 'rxjs';
import { Observable } from 'rxjs/internal/Observable';
import { FtpClientComponent } from '../ftp-client/ftp-client.component';
import { FtpClientWsService } from '../services/ftp/ftp-client-ws.service';
import { DataTableDataSource, DataTableItem } from './data-table-datasource';
@Component({
selector: 'app-data-table',
templateUrl: './data-table.component.html',
styleUrls: ['./data-table.component.css']
})
export class DataTableComponent implements AfterViewInit{
@ViewChild(MatPaginator) paginator!: MatPaginator;
@ViewChild(MatSort) sort!: MatSort;
@ViewChild(MatTable) table!: MatTable<DataTableItem>;
dataSource: DataTableDataSource;
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns = ['sftpName', 'sftpCreationDate'];
constructor(data:FtpClientComponent) {
this.dataSource = new DataTableDataSource(data);
}
ngAfterViewInit(): void {
this.dataSource.sort = this.sort;
this.dataSource.paginator = this.paginator;
this.table.dataSource = this.dataSource;
}
}
这是数据源打字稿:
import { DataSource } from '@angular/cdk/collections';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { map } from 'rxjs/operators';
import { Observable, of as observableOf, merge } from 'rxjs';
import { FtpClientComponent } from '../ftp-client/ftp-client.component';
// TODO: Replace this with your own data model type
export interface DataTableItem {
sftpName: string;
sftpCreationDate: string;
sftpPassword: string;
sftpUsedSpace: string;
sftpAllocatedSpace: string;
sftpLastModification: string;
}
// TODO: replace this with real data from your application
// const EXAMPLE_DATA: any[] = [];
/**
* Data source for the DataTable view. This class should
* encapsulate all logic for fetching and manipulating the displayed data
* (including sorting, pagination, and filtering).
*/
export class DataTableDataSource extends DataSource<DataTableItem> {
data: any[];
paginator: MatPaginator | undefined;
sort: MatSort | undefined;
constructor(data:FtpClientComponent) {
super();
this.data = data.receivedSftps
}
/**
* Connect this data source to the table. The table will only update when
* the returned stream emits new items.
* @returns A stream of the items to be rendered.
*/
connect(): Observable<DataTableItem[]> {
if (this.paginator && this.sort) {
// Combine everything that affects the rendered data into one update
// stream for the data-table to consume.
return merge(observableOf(this.data), this.paginator.page, this.sort.sortChange)
.pipe(map(() => {
return this.getPagedData(this.getSortedData([...this.data ]));
}));
} else {
throw Error('Please set the paginator and sort on the data source before connecting.');
}
}
/**
* Called when the table is being destroyed. Use this function, to clean up
* any open connections or free any held resources that were set up during connect.
*/
disconnect(): void {}
/**
* Paginate the data (client-side). If you're using server-side pagination,
* this would be replaced by requesting the appropriate data from the server.
*/
private getPagedData(data: DataTableItem[]): DataTableItem[] {
if (this.paginator) {
const startIndex = this.paginator.pageIndex * this.paginator.pageSize;
return data.splice(startIndex, this.paginator.pageSize);
} else {
return data;
}
}
/**
* Sort the data (client-side). If you're using server-side sorting,
* this would be replaced by requesting the appropriate data from the server.
*/
private getSortedData(data: DataTableItem[]): DataTableItem[] {
if (!this.sort || !this.sort.active || this.sort.direction === '') {
return data;
}
return data.sort((a, b) => {
const isAsc = this.sort?.direction === 'asc';
switch (this.sort?.active) {
case 'sftpName': return compare(a.sftpName, b.sftpName, isAsc);
case 'sftpCreationDate': return compare(+a.sftpName, +b.sftpName, isAsc);
default: return 0;
}
});
}
}
/** Simple sort comparator for example ID/Name columns (for client-side sorting). */
function compare(a: string | number, b: string | number, isAsc: boolean): number {
return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
}
ftp-client 组件只是使用一个服务来打开一个 websocket 连接来检索数据,然后存储在一个列表中
import { Component, OnInit } from '@angular/core';
import { FtpClientWsService } from '../services/ftp/ftp-client-ws.service';
@Component({
selector: 'app-ftp-client',
templateUrl: './ftp-client.component.html',
styleUrls: ['./ftp-client.component.css']
})
export class FtpClientComponent implements OnInit {
constructor(
public SftpWsService: FtpClientWsService
) { }
ngOnInit(): void {
this.SftpWsService.openWebSocket();
}
receivedSftps = this.SftpWsService.sftps;
}
该列表仅在我单击排序标题时出现, 我是 Angular 的新手,所以非常欢迎任何反馈
【问题讨论】:
-
在您的 DataTableComponent 类中,您可以尝试将属性分配从 ngAfterViewInit() 移动到 ngOnInit() 吗?设置数据绑定属性后,在 AfterView 钩子之前调用 OnInit 钩子。
-
我得到一个错误 this.table is undefined 我猜这是因为@ViewChild(MatTable) table!: MatTable
;尚未初始化 -
等待更好的方法我添加了一个等待 200 毫秒并单击 MatSort 的第一个 HTMLElement 的虚拟函数,它可以工作,但做起来很丑……
标签: angular typescript rxjs