【问题标题】:Angular Material Table Component not showing data on first loadAngular Material Table 组件在首次加载时未显示数据
【发布时间】: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


【解决方案1】:

在设置数据源值之前将 ngOninit() 的订阅添加到服务中的主题解决了问题

【讨论】:

    猜你喜欢
    • 2019-10-30
    • 2019-12-12
    • 2020-07-25
    • 1970-01-01
    • 2018-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多