Что может вызвать нулевое исключение длины свойства при использовании таблицы данных материала?

Моя проблема похожа на ту, которая обсуждалась здесь, но ни один из предложения там помогли, и моя ситуация немного другая.

У меня есть родительский компонент, назначающий массив входному свойству дочернего компонента, которое затем использует эти данные для создания источника данных для таблицы mat. Мой код похож на этот:

parent.component.html:

<mat-tab label="Accounts">
  <app-accounts [accounts]="accountOwner?.accounts"></app-accounts>
</mat-tab>

child.component.ts:

@Component({ /// })
  export class AppAccountComponent implements OnInit, OnChanges {
  @Input() accounts: MyAccount[];
tableColumns: string[] = ['name', 'number', 'startDate', 'endDate'];
accountDataSource: MatTableDataSource<MyAccount>;

@ViewChild(MatSort, { static: true }) sort: MatSort;
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;

constructor() {
  // tried this as recommended in linked thread, but it had no effect:
  // this.accountDataSource = new MatTableDataSource<MyAccount>();
}

ngOnInit(): void {
  this.sort.active = 'name';
  this.sort.direction = 'asc';
}

ngOnChanges(changes: SimpleChanges): void {
  this.accountDataSource = new MatTableDataSource<MyAccount>(this.accounts);
  this.accountDataSource.sort = this.sort;
  this.accountDataSource.paginator = this.paginator;
}
}

child.component.html:

<table mat-table [dataSource]="accountsDataSource" class="mat-elevation-z1" matSort>
  <ng-container matColumnDef="name">
    <th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
    <td mat-cell *matCellDef="let account"> {{account.name}} </td>
  </ng-container>

  <ng-container matColumnDef="number">
    <th mat-header-cell *matHeaderCellDef mat-sort-header> Number </th>
    <td mat-cell *matCellDef="let account"> {{account.number}} </td>
  </ng-container>

  <ng-container matColumnDef="startDate">
    <th mat-header-cell *matHeaderCellDef mat-sort-header> Effective Date </th>
    <td mat-cell *matCellDef="let account"> {{account.startDate | date:'mediumDate'}} </td>
  </ng-container>

  <ng-container matColumnDef="endDate">
    <th mat-header-cell *matHeaderCellDef mat-sort-header> Expiration Date </th>
    <td mat-cell *matCellDef="let account"> {{account.endDate | date:'mediumDate'}} </td>
  </ng-container>

  <tr mat-header-row *matHeaderRowDef="tableColumns"></tr>
  <tr mat-row *matRowDef="let row; columns: tableColumns;"></tr>
</table>
<mat-paginator [pageSizeOptions]="[5, 10, 20]" [disabled]="!accountsDataSource" [pageSize]="5" showFirstLastButtons>
</mat-paginator>

Интерфейс MyAccounts:

export interface MyAccount {
  number: string;
  name: string;
  startDate: Date;
  endDate?: Date;
}

Это действительно отображает данные правильно. Проблема в этом исключении в окне консоли:

введите здесь описание изображения

Это исключение "длина свойства равна нулю" выглядит так, как будто оно исходит от MatTableDataSource._filterData().


person RobC    schedule 16.06.2020    source источник
comment
Ввод вашей учетной записи может быть нулевым (не совсем, но ваш ввод не получит значения): accountOwner? .Accounts. Он запускает ngOnChanges, который заставляет вас создавать источник данных с возможным нулевым значением. Попробуйте инициализировать ввод, чтобы увидеть, исчезнет ли ошибка: @Input () accounts: MyAccount [] = new Array ‹MyAccount› ();   -  person ukn    schedule 16.06.2020
comment
@ukn Я попробовал ваше предложение, но все равно получаю то же исключение. Спасибо хоть.   -  person RobC    schedule 16.06.2020
comment
Вы должны изменить свой ngOnChanges, обновление dataSource каждый раз, когда изменяется ввод, не является хорошей идеей. Проверьте, изменилась ли учетная запись с использованием текущей или предыдущей, которую вам предоставляет SimpleChanges. Если вы хотите обновить данные, обновите только данные, не создавая новый источник данных, если он еще не существует. Последнее, что тернарный (из вашего ответа) не нужен, если остальное из того, что я сказал, было реализовано.   -  person ukn    schedule 16.06.2020
comment
@ukn Зачем обновлять источник данных, когда ввод изменяет плохую идею? Это дорого?   -  person RobC    schedule 17.06.2020
comment
Обновление - нормально, создание нового - нет. Вместо создания источника данных просто обновите данные. this.accountDataSource.data = yourData;   -  person ukn    schedule 17.06.2020


Ответы (1)


Я понял это и смущен ответом.

При первом (но не последнем) попадании в ngOnChanges массив имеет значение NULL, но в последующие разы это не так. Итак, следующие фиксированные вещи:

this.accountDataSource = new MatTableDataSource<MyAccount>(this.accounts ? this.accounts : []);
person RobC    schedule 16.06.2020