angular - «Cannot find a different support object '[object Object]'» with Observable when `*ngFor="let item of items | async" `
问题描述
我遇到了一些我不理解 Angular 的错误。因此,经过多次不成功的尝试,我来到了这里。
似乎Observable<Carte[]>
被称为object
by *ngFor
(似乎合法),但我发现的所有样本都只是 | async
用来管理它。就我而言,它失败了。
当我添加了 firestore 层来管理我的数据时发生了这个错误。顺便说一句,构造函数中的日志转储了这些数据:
[{youtubeID: "dummy", rows: 1, cols: 1},{cols: 2, rows: 2, youtubeID: "an3yLsgQVAQ"}]
环境。
Windows 上的 Ubuntu (wsl2)
Package Version
---------------------------------------------------------
@angular-devkit/architect 0.1102.10
@angular-devkit/build-angular 0.1102.10
@angular-devkit/core 11.2.10
@angular-devkit/schematics 11.2.10
@angular/cdk 11.2.10
@angular/cli 11.2.10
@angular/fire 6.1.4
@angular/material 11.2.10
@schematics/angular 11.2.10
@schematics/update 0.1102.10
rxjs 6.6.7
typescript 4.1.5
错误描述
当我尝试 *ngFor 一些带有异步管道的 observable 时,这个错误会在我的控制台中弹出。
core.js:6210 ERROR Error: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.
零件
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
import { Component } from '@angular/core';
import { AngularFirestore } from '@angular/fire/firestore';
import { Observable } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { Carousel } from './carousel/carousel.interface';
import { Dashboard } from './dashboard.interface';
import { Youtube } from './youtube/youtube.interface';
type Carte = ((Carousel | Youtube) & Dashboard);
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.scss']
})
export class DashboardComponent {
cartesStandards: Observable<Carte[]> = this.firestore.collection<Carte>('rubriques').valueChanges();
/** Based on the screen size, switch from standard to one column per row */
cards: Observable<Carte[]> = this.breakpointObserver.observe(Breakpoints.Handset).pipe(
switchMap(matches => matches ? this.cartesAjustees : this.cartesStandards)
);
get cartesAjustees() {
return this.calculeCarteAjustees()
}
constructor(
private breakpointObserver: BreakpointObserver,
private firestore: AngularFirestore
) {
this.cartesStandards.subscribe(data=>console.log(data))
}
private calculeCarteAjustees() {
return this.cartesStandards.pipe<Carte[]>(map(carte => ({ ...carte, cols: 1, rows: 1 })));
}
castVersCarousel(carte: Carte) {
if (!this.estUnCarousel(carte)) {
console.debug(carte)
throw new Error("impossible de transformer en carousel")
}
return carte as Carousel;
}
castVersYoutube(carte: Carte) {
if (!this.estUneVideoYoutube(carte)) {
console.debug(carte)
throw new Error("impossible de transformer en video youtube")
}
return carte as Youtube;
}
estUnCarousel(carte: Carte) {
return "slides" in carte && "animationType" in carte;
}
estUneVideoYoutube(carte: Carte) {
return "youtubeID" in carte
}
}
<div class="grid-container">
<h1 class="mat-h1">Services</h1>
<mat-grid-list cols="2" rowHeight="350px">
<mat-grid-tile *ngFor="let card of cards | async" [colspan]="card.cols" [rowspan]="card.rows">
<mat-card class="dashboard-card">
<ng-template [ngIf]="estUnCarousel(card)" [ngIfElse]="youtube">
<carousel [slides]="castVersCarousel(card).slides" [animationType]="castVersCarousel(card).animationType">
</carousel>
</ng-template>
<ng-template #youtube>
<youtube [youtubeID]="castVersYoutube(card).youtubeID"></youtube>
</ng-template>
</mat-card>
</mat-grid-tile>
</mat-grid-list>
</div>
解决方案
似乎该switchMap
操作导致错误的演员表(参见 Dmitry S. remark)。由于cartesStandards
正在转储一个数组,我确信卡片应该通过推理转储一个数组。
我正在寻找如何解决这种情况。
编辑
这是最终的解决方案,可能不像我想要的那么干净,但就像一个魅力。
我添加了一些重构,并延迟cols
和rows
更新 html 组件以避免嵌套 Observable。
所以这里的代码
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
import { Component } from '@angular/core';
import { AngularFirestore } from '@angular/fire/firestore';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Carousel } from './carousel/carousel.interface';
import { Dashboard } from './dashboard.interface';
import { Youtube } from './youtube/youtube.interface';
export type Carte = ((Carousel | Youtube) & Dashboard)
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.scss']
})
export class DashboardComponent {
cartesStandards = this.firestore.collection<Carte>('rubriques').valueChanges()
/** Based on the screen size, switch from standard to one column per row */
estUnPetitEcran: Observable<boolean> = this
.breakpointObserver
.observe(Breakpoints.Handset)
.pipe(map(bp => bp.matches))
constructor(
private breakpointObserver: BreakpointObserver,
private firestore: AngularFirestore
) { }
castVersCarousel(carte: Carte) {
if (!this.estUnCarousel(carte)) {
console.debug(carte)
throw new Error('impossible de transformer en carousel')
}
return carte as Carousel
}
castVersYoutube(carte: Carte) {
if (!this.estUneVideoYoutube(carte)) {
console.debug(carte)
throw new Error('impossible de transformer en video youtube')
}
return carte as Youtube
}
estUnCarousel(carte: Carte) {
return 'slides' in carte && 'animationType' in carte
}
estUneVideoYoutube(carte: Carte) {
return 'youtubeID' in carte
}
}
<div class="grid-container">
<h1 class="mat-h1">Services</h1>
<mat-grid-list cols="2" rowHeight="350px">
<mat-grid-tile *ngFor="let carte of cartesStandards | async" [colspan]="(estUnPetitEcran | async) ? 1 : carte.cols" [rowspan]="(estUnPetitEcran | async) ? 1 : carte.rows">
<mat-card class="dashboard-card">
<ng-template [ngIf]="estUnCarousel(carte)" [ngIfElse]="youtube">
<carousel [slides]="castVersCarousel(carte).slides" [animationType]="castVersCarousel(carte).animationType">
</carousel>
</ng-template>
<ng-template #youtube>
<youtube [youtubeID]="castVersYoutube(carte).youtubeID"></youtube>
</ng-template>
</mat-card>
</mat-grid-tile>
</mat-grid-list>
</div>
推荐阅读
- python-3.x - 使用 1and1 Ionos 帐户从 Python3 发送电子邮件
- android - 如何在Android App中保存最后输入的编辑文本值?
- python - 检查总订单是否细化了部分订单
- sonarqube - 如何将 .coverage 文件发送到 SonarCloud
- python - 将单元格拆分为多行并在 Pandas 中进行分组计数
- php - 使用 Symfony 5.3 检查 JWT (Firebase) 令牌
- python - Pyomo没有返回最佳状态
- bash - Bash script search for files and sleep on every 10 files found
- flutter - 来自audio_service的哨兵有很多异常
- javascript - React 17 中针对可变值内部效果的效果清理潜在问题