【问题标题】:Set custom data-source for Angular Material Table in Angular 7在 Angular 7 中为 Angular 材料表设置自定义数据源
【发布时间】:2019-07-16 10:51:17
【问题描述】:

PS:我是 Angular 和 JS 的新手。

在我的新 angular 7 项目中,我有一个 材料数据表 组件。通过 REST API,在进行 GET 调用后,我能够填充所需对象的数组。这一切都发生在组件的ngOnInit 方法中。 (不包括代码,因为它无关紧要)。

我的问题是,如何将数组绑定到数据表的dataSource?在数据表的 HTML 中,我在顶部有:

<table mat-table [dataSource]="dataSource" matSort aria-label="Elements">
  ....
  ....
  <td mat-cell *matCellDef="let row">{{row.id}}</td>
</...>

..DataSource.ts 文件中,我有一些属性和connectdisconnect 方法定义如下:

export class TestTableItem {
 id: number; 
}

export class TestTableDataSource extends DataSource<TestTableItem> {
paginator: MatPaginator;
sort: MatSort;

  constructor(private TestArray: any[]) {
   super();
  }

  connect(collections: CollectionViewer): Observable<TestTableItem[]> {
    return observableOf<TestTableItem[]>(this.TestArray);
  }

  disconnect() {}

component.ts 中,我声明了dataSource 属性,如上所述,我在ngOnInit() 方法中填充数组,如下所示:

 private myCollection: TestTableItem[] = [];

 dataSource = new MatTableDataSource(this.myCollection);

 ngOnInit() {

  ...
  //adding new item to myCollection
 }

那么,最后,我如何将数组绑定到表?我尝试在ngOnInIt 方法中将new TestTableDataSource(this.myCollection); 传递给this.dataSource,但它失败了,因为dataSourceTestTableDataSource 属于不同的类型。

不确定我是否能够正确地表达这些词,但我希望读者能明白我的意思。任何指示将不胜感激。

更新

如果我将dataSource定义为TestTableDataSource,如下:

dataSource: TestTableDataSource;

代码运行良好。但是,该表仍然是空的。有趣的是,进行此更改还会删除表的所有列。表格变得完全空白。为什么即使myCollection 不为空也会发生这种情况?

【问题讨论】:

  • TestTableDataSource 的目的是什么?我认为不需要。您想要的是将来自 Rest API 的返回数组绑定到表的数据源。我对吗?如果是,那么在 ngOnInit 上,当您的 api 中的数组被填充时(我们称之为 myArr),您只需从该数组初始化表的数据源,就像这样 this.dataSource = new MatTableDataSource(myArr);
  • @leopal,你说得对!我建议您将其添加为答案。谢谢大佬!

标签: javascript angular typescript angular-material


【解决方案1】:

无需扩展 DataSource 即可将 REST API 返回的数组绑定到 mat 表的数据源。

我的建议是:

  • 彻底删除TestTableDataSource
  • ngOnInit 上,当你的api 中的数组被填充时(我们称之为myArr),你只需要从这个数组中初始化表的数据源,就像这样this.dataSource = new MatTableDataSource(myArr);

在此之后,您的数组内容将呈现为 mat 表的数据。

【讨论】:

    【解决方案2】:

    如果您不需要分页、排序或过滤,那么@leopal 的回答就可以了。如果您确实需要这些功能,请查看 Angular Material 博客条目: Angular Material Data Table: A Complete Example (Server Pagination, Filtering, Sorting).

    它非常完整且解释清楚 - 而且太长,甚至无法涵盖这里的亮点。我看到的一个差距是如何在应用过滤器后更新分页器的总长度......下面是我的工作代码。

    页面:

    export class Page<T> extends Array<T> {
        public static readonly DEFAULT_PAGE_SIZE: number = 10;
    
        pageIndex: number;
        pageSize: number;
        totalCount: number;
    
        constructor( pgIx?: number, pgSize?: number, tot?: number, items?: T[] )
        {
            super();
            this.pageIndex = pgIx ? pgIx : 0;
            this.pageSize = pgSize ? pgSize : 0;
            this.totalCount = tot ? tot : 0;
            if ( items && items.length > 0 ) {
                this.push( ...items );
            }
        }
    }
    

    表格状态:

    import { Observable, BehaviorSubject, Observer } from "rxjs";
    import { map, catchError, finalize,
             debounceTime, distinctUntilChanged, startWith, tap, delay 
           } from "rxjs/operators";
    
    import { CollectionViewer, DataSource } from "@angular/cdk/collections";
    import { MatPaginator }                 from '@angular/material';
    
    import { MyError } from '../model/error';
    import { Page } from '../model/page';
    
    export class MyTableState<T> implements DataSource<T>, Observer<Page<T>> 
    {
        private items = new BehaviorSubject<Page<T>>( new Page<T>() );
        private loading = new BehaviorSubject<boolean>(false);
        private err = new BehaviorSubject<DruidError>( new DruidError(0, '') );
        
        protected paginator: MatPaginator;
    
        items$ = this.items.asObservable();
        loading$ = this.loading.asObservable();
        error$ = this.err.asObservable();
        
        closed = false;
        
        constructor( protected itemType: string ) {
        }
        
        haveError() : boolean {
            const derr = this.err.getValue();
            if ( derr && (derr.status !== 0 || derr.message) ) {
                return true;
            }
            return false;
        }
    
        errorStatus() : number {
            const derr = this.err.getValue();
            if ( derr ) {
                return derr.status;
            }
            return 0;
        }
    
        errorMessage() : string {
            const derr = this.err.getValue();
            if ( derr ) {
                return derr.message;
            }
            return '';
        }
    
        noResults() : boolean {
            const results = this.items.getValue();
            return !results || results.length == 0;
        }
    
        isLoading() : Observable<boolean> {
            return this.loading$;
        }
    
        totalCount() : number {
            const cnt = this.items.getValue();
            return ( cnt ? cnt.totalCount : 0 );
        }
    
        next( results: Page<T> ) : void {
            console.debug( "Found items: ", this.itemType, results );
            if ( this.paginator ) {
                this.paginator.length = results.totalCount;
            }
            this.items.next( results );
        }
        error( errr: any ) : void {
            console.error( "Error loading items: ", this.itemType, errr );
            this.err.next( errr );
        }
        complete() : void {
            console.debug( "Done loading items.", this.itemType );
            this.loading.next( false );
        }
    
        addItem( item: T ) : void {
            this.items.value.unshift( item );
        }
    
        connect( collectionViewer: CollectionViewer ) : Observable<Page<T>> {
            this.closed = false;
            return this.items$;
        }
    
        disconnect( collectionViewer: CollectionViewer ): void {
            this.closed = true;
            this.items.complete();
            this.loading.complete();
            this.err.complete();
        }
        
        protected preLoad() : void {
            this.err.next( new DruidError(0,'') );
            this.loading.next( true );
        }
    
        setPaginator( pgntr: MatPaginator ) : void {
            this.paginator = pgntr;
        }
    
        /* In a derived class implement this and call it from your containing 
         * components in response to filter input, etc.
        loadXyzs( offset: number = 0, limit: number = 10, predicates?: any ) : void
        {
            this.preLoad();
    
            this.xyzService
                .searchXyzs( offset, limit, predicates )
                .subscribe( this );
        }*/  
    };
    

    【讨论】:

      【解决方案3】:

      您正在创建不同的垫表

      您可以使用@ViewChild 指令获取对在 HTML 中呈现的 mat-table 的引用

      @ViewChild('matTable') matTable: MatTable;
      
      ngAfterViewInit() {
        this.matTable.data = yourData;
      }
      

      或者您可以在 HTML 中使用 mat-table 数据源输入:

      <table mat-table [dataSource]="yourDataSource">
       // Your HTML
      </table
      

      然后 changeDetection 将为您完成剩下的工作

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-05-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多