【问题标题】:Angular 6 material table schematic: howto load data from remote?Angular 6材料表示意图:如何从远程加载数据?
【发布时间】:2018-09-13 01:53:28
【问题描述】:

我正在使用material table schematic,但不知道如何使用

我认为重要的部分是datasource.ts 文件中的connect() 方法。 this.data 只是一个数组。

  /**
   * 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<any[]> {
    // Combine everything that affects the rendered data into one update
    // stream for the data-table to consume.
    const dataMutations = [
      observableOf(this.data),
      this.paginator.page,
      this.sort.sortChange
    ];

    // Set the paginators length
    this.paginator.length = this.data.length;

    return merge(...dataMutations).pipe(
      map(() => {
        return this.getPagedData(this.getSortedData([...this.data]));
      })
    );
  }

如何更新this.data 以使表格反映数据?我只需要加载一次数据。我希望过滤/排序等都在客户端完成。

我找到了this guide,但这似乎有点矫枉过正,并且是在创建此原理图之前编写的。

由于this.data 包裹在observableOf() 中,难道没有办法更新它吗?

【问题讨论】:

  • 查看this article 以获取有关如何使用connect()BehaviorSubjects 让您的表反映数据更改的一个很好的示例。简而言之,您将使用服务来获取更新的数据,并且您的 DataSource 类将订阅更改,并相应地更新表。
  • 谢谢,但是那是我在我的 q 中链接到的文章。除了我对上面文章的评论之外,这个例子还做了服务器端的过滤和排序。

标签: angular angular-material observable angular-material2 angular2-observables


【解决方案1】:

表的数据源需要是Observable

只要this.data是一个数组,就没有机制会在数组中添加、删除或修改项目时通知数据表。

【讨论】:

  • 您是说用Observable 替换observableOf(this.data) 行一样简单吗?我不太了解 rxjs 或 Angular,无法实现飞跃/连接点。似乎我的用例很常见,但是很难找到一个干净/不太复杂的完整示例。我知道这是一个很大的问题,但你有没有机会堆叠一些东西?
【解决方案2】:

在搜索教程后,我回复到the Official Example,结果证明它非常直观。

我对您的问题有类似的要求,只需加载一次数据并在客户端管理操作。

但是,我结束了在服务器端处理操作。

让我做一个假设,你有一个返回对象列表的端点。

/api/books/

1:使用 http-call 方法创建服务以获取您的图书端点(book.service.ts)

private booksUrl = "/api/books";
 _getBooks(bookId: number, filter='', sortOrder='asc', pageNumber=0, 
pageSize=3):Observable<Book[]>{
    return this.http.get(this.booksUrl, {
      params: new HttpParams()
          .set('bookId', _bookId.toString())
          .set('filter', filter)
          .set('sortOrder', sortOrder)
          .set('pageNumber', pageNumber.toString())
          .set('pageSize', pageSize.toString())
      }).pipe(
          tap(_ => this.log('fetched books')),
          catchError(this.handleError('getBooks', [])),
          map(res =>  {
        res["payload"] = res;
        return res["payload"];
      })
      );
    }

定义你的 Book 类

export class Book{
    bookId: string;
    Title: string;
}

然后我使用数据表原理图创建了一个 Material-Table 组件。

我这样编辑了表数据源

import { Book } from '../books';
import { BookService } from '../book.service';


/**
 * Data source for the Masterlist view. This class should
 * encapsulate all logic for fetching and manipulating the displayed data
 * (including sorting, pagination, and filtering).
 */
export class BooksDataSource implements DataSource<Book> {

  private booksSubject = new BehaviorSubject<Book[]>([]);
  private loadingSubject = new BehaviorSubject<boolean>(false);

  public loading$ = this.loadingSubject.asObservable();

  constructor(private bookService: BookService) {}

  /**
   * 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( collectionViewer:CollectionViewer): Observable<Book[]> {
    return this.booksSubject.asObservable();
  }

  /**
   *  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(collectionViewer: CollectionViewer): void {
    this.booksSubject.complete();
    this.loadingSubject.complete();
  }

  loadBooks(bookId: number, filter = '', sortDirection = 'asc', pageIndex = 0, pageSize = 3) {
    this.loadingSubject.next(true);
    this.bookService._getBook(bookId, filter, sortDirection,pageIndex, pageSize).pipe(
      catchError(e => throwError(e)),

      finalize(() => this.loadingSubject.next(false))
      )
      .subscribe(_books => this.booksSubject.next(_books));
}    
}

最后,在 Books.Components.ts(你的组件)

export class BooksComponent implements OnInit {

  constructor(private bookService: BookService){}

  dataSource: BooksDataSource;

  /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
  displayedColumns = ['bookId', 'Title'];

  ngOnInit() {
    this.dataSource = new MasterlistDataSource(this.bookService);
    this.dataSource.loadBooks(1);
  }
}

您可以从这里将数据源映射到您的表。

the Official Example 继续展示如何实现排序、分页、过滤。

编码愉快 :-)

【讨论】:

    【解决方案3】:

    我遇到了同样的问题。 observableOf(this.data), 未检测到更改 dataSource.data = newData

    使用来自this thread 的解决方案修复它并显示在this example 中。

    您必须将 observableOf(this.data) 替换为 this.datastream。所以连接方法最终看起来像这样:

    connect(): Observable<DataTableItem[]> {
      const dataMutations = [
      this.dataStream,
      this.paginator.page,
      this.sort.sortChange
    

    并且在课程的开头,您没有声明变量data: TableItem[] = EXAMPLE_DATA;,而是将其替换为:

    dataStream = new BehaviorSubject<DataTableItem[]>(EXAMPLE_DATA);
    set data(v: DataTableItem[]) { this.dataStream.next(v); }
    get data(): DataTableItem[] { return this.dataStream.value; }
    

    现在,您可以在任何地方使用任何新数据致电dataSource.data = newData,它就可以正常工作。数据流检测到更改并更新表。问题是 this.data 的 observable 并没有真正检测到任何变化。数据流确实如此。

    【讨论】:

      【解决方案4】:

      请尝试@matheo/datasource 以干净的方式设置您的数据库服务和数据源。

      我已经在 StackBlitz 上构建了一个演示,并在以下地址展示了它的详细信息:
      https://medium.com/@matheo/reactive-datasource-for-angular-1d869b0155f6

      我会争取时间提供一个原理图,其中包含一些样板代码作为官方材料。
      期待您的意见!

      【讨论】:

        猜你喜欢
        • 2019-01-03
        • 1970-01-01
        • 2018-10-29
        • 1970-01-01
        • 1970-01-01
        • 2019-04-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多