Ошибка: InvalidPipeArgument: '[object Object]' для канала 'AsyncPipe' MatTable Angular 11

Я пытаюсь использовать Angular MatTable с асинхронным каналом. Я получаю данные из RESTAPI как Observable. Однако, когда я использую ([dataSource] = dataSource | async) таким образом, я получаю ошибку, о которой я упоминал выше.

репозиторий.service.ts:

public GetList(controller: string): Observable<T[]> {
return this.httpclient.get<T[]>(this.apiURL + '/' + controller + '/getList', { headers: this.headers });}

контакт.component.ts:

ngOnInit() {
this.contactService.GetList("OfferContact").subscribe(res => {
  this.ContactList = res
  this.setFunctions(this.ContactList)
})} 
setFunctions(list) {
  this.dataSource.data = list;
  this.spinner.hide()
  this.dataSource.paginator = this.paginator;
  this.dataSource.sort = this.sort;
  }

contact.component.html:

           <table mat-table [dataSource]="dataSource|async" matSort>

                <ng-container matColumnDef="company">
                    <th mat-header-cell *matHeaderCellDef mat-sort-header> Firma Adı </th>
                    <td mat-cell *matCellDef="let element"> {{element.company}} </td>
                </ng-container>

                <ng-container matColumnDef="name">
                    <th mat-header-cell *matHeaderCellDef mat-sort-header> Yetkili Adı </th>
                    <td mat-cell *matCellDef="let element"> {{element.name}} </td>
                </ng-container> 
                   ...
                 </table>
            <mat-paginator [pageSizeOptions]="[20, 30, 50, 70, 100]"></mat-paginator>

Ошибка

ERROR Error: InvalidPipeArgument: '[object Object]' for pipe 'AsyncPipe'

это скриншот. Как вы можете видеть в правом нижнем углу, данные извлекаются, но не обрабатываются в таблице.

Кто-нибудь может помочь с этой проблемой?


person Bilal GÖZET    schedule 18.01.2021    source источник


Ответы (2)


Как говорится в ошибке, канал async можно использовать только в сочетании с наблюдаемым. Вместо этого вы пытаетесь получить ответ от наблюдаемого.

Вариант 1: без трубы async

Вы можете просто удалить трубу async. Это может вызвать ошибку в консоли при инициализации компонента, когда переменная dataSource равна undefined.

<table mat-table [dataSource]="dataSource" matSort>
    <ng-container matColumnDef="company">
        <th mat-header-cell *matHeaderCellDef mat-sort-header> Firma Adı </th>
        <td mat-cell *matCellDef="let element"> {{element.company}} </td>
    </ng-container>

    <ng-container matColumnDef="name">
        <th mat-header-cell *matHeaderCellDef mat-sort-header> Yetkili Adı </th>
        <td mat-cell *matCellDef="let element"> {{element.name}} </td>
    </ng-container> 
        ...
</table>
<mat-paginator [pageSizeOptions]="[20, 30, 50, 70, 100]"></mat-paginator>

Вариант 2: с трубой async

Вы можете назначить HTTP-запрос переменной в контроллере. Затем вы можете использовать оператор map, чтобы установить свойства data, paginator и sort, и оператор finalize, чтобы скрыть счетчик.

Попробуйте следующее

Контроллер

dataSource$: Observable<any>;  // <-- define it as an observable ('$' at end is convention)
ngOnInit() {
  this.dataSource$ = this.contactService.GetList("OfferContact").pipe(
    tap(res => {
      this.ContactList = res   // <-- is `this.ContactList` even required?
    }),
    map(dataSource => ({
      ...dataSource, 
      dataSource['data']: res,
      dataSource['paginator']: this.paginator,
      dataSource['sort']: this.sort
    })),
    finalize(() => this.spinner.hide())
  );
}

Шаблон

<ng-container *ngIf="(dataSource$ | async) as dataSource">   <!-- wrap it in *ngIf to reuse the response -->
    <table mat-table [dataSource]="dataSource" matSort>
        <ng-container matColumnDef="company">
            <th mat-header-cell *matHeaderCellDef mat-sort-header> Firma Adı </th>
            <td mat-cell *matCellDef="let element"> {{element.company}} </td>
        </ng-container>

        <ng-container matColumnDef="name">
            <th mat-header-cell *matHeaderCellDef mat-sort-header> Yetkili Adı </th>
            <td mat-cell *matCellDef="let element"> {{element.name}} </td>
        </ng-container> 
            ...
    </table>
    <mat-paginator [pageSizeOptions]="[20, 30, 50, 70, 100]"></mat-paginator>
</ng-container>

Изменить: изменить res на dataSource внутри оператора map

person Michael D    schedule 18.01.2021
comment
Честно говоря, я не знаю, как использовать операции внутри функции map (...). Например, ... dataSource, => Cannot find name 'dataSource'. Did you mean the instance member 'this.dataSource'? выдает предупреждение. dataSource.data: res, =› An object literal cannot have multiple properties with the same name in strict mode. выдает предупреждение. Я не знаю, является ли ... dataSource аббревиатурой или употреблением. - person Bilal GÖZET; 18.01.2021
comment
Это была моя ошибка. Я присвоил ответ переменной res вместо dataSource. Я обновил ответ. Также я заменил запись через точку записью в квадратных скобках, чтобы избежать возможных ошибок undefined от TS Linter. Пожалуйста, попробуйте решение еще раз. - person Michael D; 18.01.2021
comment
спасибо вам и Акифу за ваши усилия. Это не сработало. Я буду использовать первое решение - person Bilal GÖZET; 18.01.2021

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

 [dataSource]="dataSource"

Как упоминалось в официальной документации, вы можете использовать асинхронный канал с observable или promise. Но в вашем случае ваш источник данных не является наблюдаемым или обещанием. Ваш метод getList доступен для наблюдения. Таким образом, вы не можете использовать асинхронный канал с вашим источником данных, как вы пытались.

person Akif    schedule 18.01.2021
comment
Я знаю это использование. Но когда я использую это, для загрузки страницы требуется 10-15 секунд. Поэтому я хотел использовать асинхронный канал. Он загружается сразу, но не строки данных - person Bilal GÖZET; 18.01.2021
comment
Я отредактировал ответ. У @Michael D есть хорошее объяснение ваших требований. - person Akif; 18.01.2021