在 Mat-Table (Angular) 中显示分页数据

Displaying Paginated Data in Mat-Table (Angular)

我有一个 CRUD REST API,它将分页数据发送到客户端。考虑以下数据接口:

export interface LCKData {
    // Some basic type fields from DB
}

export interface LCKPageData {
    content: LCKData[],
    pageable: any,
    totalElements: number,
    totalPages: number,
    last: boolean,
    numberOfElements: number,
    size: number,
    number: number,
    sort: any,
    first: boolean,
    empty: boolean
}

第二个接口是来自 Spring 启动 Web 应用程序的标准分页数据。我使用这个结构来设置 Paginator 组件属性,即总页数。

我使用这两个服务来获取数据并创建数据源:

let LCKBaseAddress: string = "...";

@Injectable()
export class LockService {

    constructor(private http: HttpClient) { }

    findLCK(sortColumn = "sysTime", sortOrder = 'desc',
        pageNumber = 0, pageSize = 10): Observable<LCKPageData> {
        return this.http.get(LCKBaseAddress, {
            params: new HttpParams()
                .set('q', sortColumn)
                .set('d', sortOrder)
                .set('p', pageNumber.toString())
                .set('s', pageSize.toString())
        }).pipe(map(res => {
            res['payload'] = res;
            return res["payload"];
        }))
    };
   
}

并且:

export class MainService extends DataSource<LCKData>{

    private loadingSubject = new BehaviorSubject<boolean>(false);
    private pageSubject = new BehaviorSubject<LCKData[]>([]);
    private locks$ = new Observable<LCKPageData>();
   
    constructor(private lockService: LockService) {
        super();
    };

    connect(collectionViewer: CollectionViewer): Observable<LCKData[]> {
        return this.locks$.pipe(pluck("content"));
    }

    disconnect(collectionViewer: CollectionViewer): void {
      this.loadingSubject.complete();
      this.pageSubject.complete();
    }

    loadLCK(sortColumn = "sys_time", sortOrder = 'desc',
        pageNumber = 0, pageSize = 10) {
        this.lockService.findLCK(sortColumn, sortOrder, pageNumber, pageSize).pipe(
            catchError(() => of([])),
            finalize(() => this.loadingSubject.next(false))
        )
            .subscribe(lcks => this.pageSubject.next(lcks['content']));
    }
}

最后是 table 组件:

@Component({
  selector: 'app-table',
  templateUrl: './table.component.html',
  styleUrls: ['./table.component.css']
})
export class TableComponent implements OnInit {

  public columns: string[];

  dataSource: MainService;

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

  constructor(public lock: LockService) {}

  ngOnInit(): void {
    this.dataSource = new MainService(this.lock);
    this.dataSource.loadLCK();
    this.columns = [ // Some columns //];
  }

  ngAfterViewInit() {
    this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0);
    merge(this.sort.sortChange, this.paginator.page)
      .pipe(
        tap(() => this.loadLessonsPage())
      )
      .subscribe();
  }

  loadLessonsPage() {
    this.dataSource.loadLCK(
      'sysTime',
      this.sort.direction,
      this.paginator.pageIndex,
      this.paginator.pageSize);
  }

}

和模板:

<table mat-table [dataSource]="dataSource" class="mat-elevation-z2" matSort matSortActive="sysTime"
        matSortDirection="desc" matSortDisableClear>
// Column and row definition

代码运行没有任何错误,但 table 中没有显示任何内容。

之前我用非分页数据测试了相同的方法,一切正常,服务器响应 List 而不是 LCKPageData。

我用Angular10.

有什么想法吗?

您的 connect() 方法 returns 一个从不发射的可观察对象!

与其将 locks$ 初始化为新的可观察对象,不如将其定义为 pageSubject

private locks$: Observable<LCKData[]> = this.pageSubject.asObservable();

无需使用 pluck,因为您已经将 content 属性 发送到主题 (this.pageSubject.next(lcks['content'])):

connect(collectionViewer: CollectionViewer): Observable<LCKData[]> {
   return this.locks$;
}