首页 文章

Angular Material Table - 映射服务器响应以满足DataSource Contract

提问于
浏览
2

我正在组合一个Angular Material Table来显示从服务器返回的结果 . 数据结构如下:

export class Question
{
    question        : string;
    anonymous       : boolean;
}

export class SearchResult
{
    totalCount      : number;
    pageBeginIndex  : number;
    pageSize        : number;
    questions       : Question[];
}

http get包含在一个计算为observable的函数中:

public getSearchQuestions = (queryString : string, startIndex : number, count : number): Observable<SearchResult> =>
{
    let url = this.baseUrl + "search?queryString=" + queryString + "&startIndex=" + startIndex + "&count=" + count;
    return this.http.get(url, { headers : this.getHeaders() })
        .map(response => response.json() as SearchResult)
        .catch(error => this.handleError(error));
}

我遇到的问题是Table的DataSource定义中的connect()函数 . 典型的示例显示了一个函数的返回,该函数直接从服务器评估到Observable []获取结果 . 我的情况更复杂,因为我需要通过http get函数提取Observable返回,这是DataSource :: connect() Contract 所需的Observable的包装器 . 我不想在http get数据映射中进行这种解包,因为我还需要同时提取DataSource中的totalCount字段 . 这是我必须达到的地方:

export class SearchDataSource extends DataSource<any>
{
    recordCount : number;

    constructor(private service: IntelienceService, private searchQuery : string, private _paginator: MatPaginator) {
      super();
    }

    connect(): Observable<Question[]> {

        const startIndex = this._paginator.pageIndex * this._paginator.pageSize;

        return Observable.create((observer) : Observable<Question[]> => {
            return this.service.getSearchQuestions(this.searchQuery, startIndex, this._paginator.pageSize).map(
              searchResult => {

                // Execution never reaches here

                this.recordCount = searchResult.totalCount;
                return searchResult.questions },
              error => { console.log('error') }   
            );
        });
      }

      disconnect() { }
    }

虽然这会编译Table的Paginator会抛出一个内部错误,表明从connect返回的值是未定义的 - 实际上执行永远不会达到上述代码中注释所指示的点 . 任何帮助,以了解如何创建一个新的Observable包装现有的Observable并以我指示的方式映射数据将非常感激 .

===编辑===

我对此修订版进一步了解:

connect(): Observable<SearchQuestion[]> {

const startIndex = this._paginator.pageIndex * this._paginator.pageSize;

return Observable.create(observer => {
  this.service.getSearchQuestions(this.searchQuery, startIndex, this._paginator.pageSize).subscribe(
    (searchResults) => {
      observer.next(() => { return searchResults.questions; });
      observer.complete();
    },
    error => { console.log('error') }
  );
});
}

现在调用getSearchQuestions中的http get,但是没有调用observer.next()函数,并且paginator继续抛出未定义的错误:

ERROR TypeError: Cannot read property 'pageIndex' of undefined
    at SearchDataSource.webpackJsonp.../../../../../src/app/search/search.component.ts.SearchDataSource.connect (search.component.ts:61)

1 回答

  • 2

    你根本不需要 Observable.create() .

    startIndex 不应该是常量,每次翻页时都应该计算它 .

    export class SearchDataSource extends DataSource<Question> {
    
      recordCount: number;
    
      constructor(private intelienceService: IntelienceService,
                  private searchQuery: string,
                  private _paginator: MatPaginator) {
        super();
      }
    
      connect(): Observable<Question[]> {
    
        return this.intelienceService.getSearchQuestions(this.searchQuery, this.getStartIndex(), this._paginator.pageSize)
          .map(searchResult => {
              this.recordCount = searchResult.totalCount;
              return searchResult.questions;
            }, () => { console.log('error'); }
          );
      }
    
      disconnect() {
        // intentionally left blank
      }
    
      private getStartIndex(): number {
        return this._paginator.pageIndex * this._paginator.pageSize;
      }
    
    }
    

    Bonus:

    您应该使用http选项,而不是插入网址:

    this.http.get(url, {
      headers: this.getHeaders(),
      params: {
        queryString: queryString,
        startIndex: startIndex,
        count: count
      }
    });
    

    此外,服务名称中还有一个小错字:

    IntelienceService => IntelligenceService
    

相关问题