ngx-datatable Невозможно переназначить строковую модель в случае [rows] = rows | асинхронный

Я использую Angular 2 (4.1.0), angularfire2 и ngx-datatable.

У меня есть компонент с таблицей данных, который отображает Observable. Observable основан на Angularfire2. Пользователь может фильтровать столбец имени, как в демонстрации фильтра ngx-datatable. Я запрашиваю у firebase новый набор результатов и пытаюсь назначить новый Observable строковой модели таблицы данных, но это не работает:

ERROR TypeError: Cannot read property '0' of null
    at DataTableBodyComponent../src/components/body/body.component.ts.DataTableBodyComponent.updateRows (index.js:4384)
    at DataTableBodyComponent../src/components/body/body.component.ts.DataTableBodyComponent.recalcLayout (index.js:4599)
    at DataTableBodyComponent.set [as rows] (index.js:4185)
    at updateProp (core.es5.js:10966)
    at checkAndUpdateDirectiveDynamic (core.es5.js:10726)
    at checkAndUpdateNodeDynamic (core.es5.js:12111)
    at checkAndUpdateNode (core.es5.js:12055)
    at debugCheckAndUpdateNode (core.es5.js:12681)
    at debugCheckDirectivesFn (core.es5.js:12622)
    at Object.eval [as updateDirectives] (DatatableComponent.html:24)
    at Object.debugUpdateDirectives [as updateDirectives] (core.es5.js:12607)
    at checkAndUpdateView (core.es5.js:12019)
    at callViewAction (core.es5.js:12334)
    at execComponentViewsAction (core.es5.js:12280)
    at checkAndUpdateView (core.es5.js:12025)

Ожидаемое поведение:

После фильтрации и получения нового Observable я хочу, чтобы datatable отображал новый Observable.

Вот наиболее важные фрагменты кода:

HTML, Datatable (я использую [rows] = "rows | async"!):

...
<ngx-datatable #table [rows]="rows | async" 
 [columnMode]="'flex'" [headerHeight]="50" [footerHeight]="50" [rowHeight]="'auto'"
 [limit]="10" class="material striped" [selected]="selected" [selectionType]="'single'"
 (select)='onSelect($event)'>
...

Компонент:

@Input()
  set onFilteringList (filter: string) {
    this._onFilteringList = filter;
    // assignment after the table has been rendered throws error!
    this.rows = this.workItemSrv.getFilteredByUserWorkItemList(this.onFilteringList);
  }
ngOnInit() { // OK, everything worked fine here 
    if (this.onFilteringList) {
      this.rows = this.workItemSrv.getFilteredByUserWorkItemList(this.onFilteringList);
    } else {
      this.rows = this.workItemSrv.getWorkItemList();
    }
  }

Я пробовал три разных способа отображения отфильтрованного набора результатов:

  1. Маршрутизация: использование параметров маршрута (в качестве параметров фильтра) выглядит многообещающим, но компонент не инициализируется повторно при каждой навигации. После начальной маршрутизации, инициализации компонента и рендеринга таблицы я получаю ошибку, подобную описанной выше (см. Фрагменты кода).

  2. используя методы запроса firebase, но нет способа определить запрос с параметром, чтобы либо были извлечены все элементы, либо отфильтрованное подмножество всех элементов. Использование Observable с примененным фильтром и второго Observable без фильтра может быть решением, но мне нужно поменять местами модель строки на datatable. И это приводит к ошибке, как указано выше.

  3. используя метод фильтра rxjs, но я не нашел решения, чтобы успешно применить фильтр к наблюдаемому

Ни один из них не дает мне решения. :-(

Как я могу изменить строковую модель таблицы данных или выполнить фильтрацию в Observable?

Спасибо, Маркус


person CitizenOfGreenland    schedule 18.05.2017    source источник


Ответы (1)


Вы можете попытаться избежать использования асинхронной модели данных:

...
<ngx-datatable #table [rows]="rows" 
...

И компоненты меняются:

@Input()
set onFilteringList (filter: string) {
  this._onFilteringList = filter;
  this.workItemSrv.getFilteredByUserWorkItemList(this.onFilteringList)
    .subscribe(rows => this.rows = rows);
}

ngOnInit() { 
  if (this.onFilteringList) {
    this.rows = 
    this.workItemSrv.getFilteredByUserWorkItemList(this.onFilteringList)
       .subscribe(rows => this.rows = rows);
  } else {
    this.rows = this.workItemSrv.getWorkItemList()
      .subscribe(rows => this.rows = rows);
  }
}
person hiper2d    schedule 18.05.2017
comment
Работает как шарм. :-) Не знаю, почему я не попробовал предложенное вами решение? Очевидно, я все еще новичок в JavaScript. ;-) - person CitizenOfGreenland; 19.05.2017
comment
Если вы используете ChangeDetectionStrategy.OnPush, это не сработает. - person David Ćeranić; 08.03.2021