如何在 Observable 中使用 Angular ngFor
How to use Angular ngFor with Observable
与 Book
class 定义为:
class Book {
id: number;
name: string;
constructor(id: number, name: string) {
this.id = id;
this.name = name;
}
}
我继续创建 Observable
对象 books$
:
const book1: Book = new Book(1, "Title 1");
const book2: Book = new Book(2, "Title 2");
function booklist(observer) {
observer.next(book1);
observer.next(book2);
observer.complete();
return {unsubscribe() {}};
}
this.books$ = new Observable(booklist);
正在检查:
this.books$.subscribe(each => console.log(each));
打印:
Book {id: 1, name: "Title 1"}
Book {id: 2, name: "Title 2"}
但是在 html 模板中将此 observable 与 ngFor
一起使用:
<ul>
<li *ngFor="let book of books$ | async" >
Id: {{book.id}}, Name: {{book.name}}
</li>
</ul>
提高 ERROR
:
Error: Cannot find a differ supporting object '[object Object]' of type 'Title 2'. NgFor only supports binding to Iterables such as Arrays.
如何解决这个问题?这是 link 到 Stackblitz 项目:
https://stackblitz.com/edit/angular-ivy-isebs7?file=src%2Fapp%2Fapp.component.ts
一切看起来都不错,除了 books$
表示对象流,而不是数组。所以可能必须使用 keyvalue
管道。尝试以下
<ul>
<ng-container *ngIf="(books$ | async) as books">
<li *ngFor="let book of books | keyvalue" >
{{book.key}}: {{book.value}}
</li>
</ng-container>
</ul>
更新:RxJS bufferCount
运算符
然而,上述解决方案仅打印当前通知。如果你想收集每个通知并显示它们,你可以使用 RxJS bufferCount
(or buffer
如果你不准确的通知数量)运算符收集所有通知。
控制器
import { bufferCount } from 'rxjs/operators';
ngOnInit(): void {
...
this.books$ = <Observable<Book[]>>(new Observable(booklist).pipe(bufferCount(2)));
this.books$.subscribe(each => console.log(each));
}
模板
<ul>
<ng-container *ngFor="let books of books$ | async">
<li *ngFor="let book of books | keyvalue" >
{{book.key}}: {{book.value}}
</li>
</ng-container>
</ul>
我修改了你的Stackblitz
我会将此行为提取到一个新方法中:
getBooksArr$: Observable<Book[]> {
return this.books$.pipe(map((book) => Object.values(book)));
}
在html中:
<ul>
<li *ngFor="let book of getBooksArr$() | async" >
Id: {{book.id}}, Name: {{book.name}}
</li>
</ul>
与 Book
class 定义为:
class Book {
id: number;
name: string;
constructor(id: number, name: string) {
this.id = id;
this.name = name;
}
}
我继续创建 Observable
对象 books$
:
const book1: Book = new Book(1, "Title 1");
const book2: Book = new Book(2, "Title 2");
function booklist(observer) {
observer.next(book1);
observer.next(book2);
observer.complete();
return {unsubscribe() {}};
}
this.books$ = new Observable(booklist);
正在检查:
this.books$.subscribe(each => console.log(each));
打印:
Book {id: 1, name: "Title 1"}
Book {id: 2, name: "Title 2"}
但是在 html 模板中将此 observable 与 ngFor
一起使用:
<ul>
<li *ngFor="let book of books$ | async" >
Id: {{book.id}}, Name: {{book.name}}
</li>
</ul>
提高 ERROR
:
Error: Cannot find a differ supporting object '[object Object]' of type 'Title 2'. NgFor only supports binding to Iterables such as Arrays.
如何解决这个问题?这是 link 到 Stackblitz 项目:
https://stackblitz.com/edit/angular-ivy-isebs7?file=src%2Fapp%2Fapp.component.ts
一切看起来都不错,除了 books$
表示对象流,而不是数组。所以可能必须使用 keyvalue
管道。尝试以下
<ul>
<ng-container *ngIf="(books$ | async) as books">
<li *ngFor="let book of books | keyvalue" >
{{book.key}}: {{book.value}}
</li>
</ng-container>
</ul>
更新:RxJS bufferCount
运算符
然而,上述解决方案仅打印当前通知。如果你想收集每个通知并显示它们,你可以使用 RxJS bufferCount
(or buffer
如果你不准确的通知数量)运算符收集所有通知。
控制器
import { bufferCount } from 'rxjs/operators';
ngOnInit(): void {
...
this.books$ = <Observable<Book[]>>(new Observable(booklist).pipe(bufferCount(2)));
this.books$.subscribe(each => console.log(each));
}
模板
<ul>
<ng-container *ngFor="let books of books$ | async">
<li *ngFor="let book of books | keyvalue" >
{{book.key}}: {{book.value}}
</li>
</ng-container>
</ul>
我修改了你的Stackblitz
我会将此行为提取到一个新方法中:
getBooksArr$: Observable<Book[]> {
return this.books$.pipe(map((book) => Object.values(book)));
}
在html中:
<ul>
<li *ngFor="let book of getBooksArr$() | async" >
Id: {{book.id}}, Name: {{book.name}}
</li>
</ul>