模板不使用异步管道呈现可观察的
Template does not render observable using async pipe
我刚开始使用 angular,在试图了解自己发生了什么之后,我就是想不出解决方案。我有一个简单的模板:
<div *ngIf="allProducts$ | async as products">
<div *ngIf="products.size > 0; else noProducts">
<ul>
<li *ngFor="let product of products" >
<span>{{product.id}}</span>
<span>{{product.name}}</span>
<span (click)="productDetail(product)">Go to detail</span>
</li>
</ul>
</div>
<ng-template #noProducts>There are no products yet.</ng-template>
</div>
与 class:
import {Component, OnInit} from '@angular/core';
import {Observable} from 'rxjs';
import {Product} from '../../model/product';
import {Router} from '@angular/router';
import {ProductService} from '../../service/product.service';
@Component({
selector: 'app-product-list',
templateUrl: './product-list.component.html',
styleUrls: ['./product-list.component.css']
})
export class ProductListComponent implements OnInit {
public allProducts$: Observable<Product[]>;
constructor(private router: Router,
private productService: ProductService) {}
ngOnInit() {
console.log('constructing ProductListComponent');
this.allProducts$ = this.productService.getAllProducts();
}
productDetail(product: Product) {
this.router.navigate([`product/${product.id}`]);
}
}
最后,服务:
import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {API_URL} from '../../app.constants';
import {Product} from '../model/product';
import {first, map} from 'rxjs/operators';
import {BehaviorSubject, Observable} from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ProductService {
constructor(private http: HttpClient) {
}
addProduct(product: Product) {
return this.http.post<Product>(`${API_URL}/product`, product, {observe: 'response'});
}
getAllProducts(): Observable<Product[]> {
return this.http.get<Product[]>(`${API_URL}/product`, {observe: 'response'})
.pipe(map(response => response.body), first());
}
}
很简单的东西。我只是无法让它呈现。所以我尝试在服务中创建一个行为主题并将其订阅到http observable,并将其返回给组件而不是原始的http observable,认为可能组件没有机会及时订阅,如this中所述。没有运气。
接下来,受 this SO question 的启发,我尝试在订阅中手动调用 markForCheck,完全删除异步管道。再一次,什么都没有。
我找不到任何其他解决方案,但这两个是最常见的方法,而且它似乎在任何地方都有效,比如 here or here. Why doesn't it work for me? Clearly, there is something simple eluding me. When I log the response body in the console in the subscription lambda, I can see the product entities I expect from backend, but neither async pipe or subscription in ngOnInit work. I have also seen an approach using ,但我觉得可以简单地完成同样的事情作为常规订阅和 markForCheck。
这看起来不对...
<div *ngIf="products.size > 0; else noProducts">
你的意思是:
<div *ngIf="products.length > 0; else noProducts">
我刚开始使用 angular,在试图了解自己发生了什么之后,我就是想不出解决方案。我有一个简单的模板:
<div *ngIf="allProducts$ | async as products">
<div *ngIf="products.size > 0; else noProducts">
<ul>
<li *ngFor="let product of products" >
<span>{{product.id}}</span>
<span>{{product.name}}</span>
<span (click)="productDetail(product)">Go to detail</span>
</li>
</ul>
</div>
<ng-template #noProducts>There are no products yet.</ng-template>
</div>
与 class:
import {Component, OnInit} from '@angular/core';
import {Observable} from 'rxjs';
import {Product} from '../../model/product';
import {Router} from '@angular/router';
import {ProductService} from '../../service/product.service';
@Component({
selector: 'app-product-list',
templateUrl: './product-list.component.html',
styleUrls: ['./product-list.component.css']
})
export class ProductListComponent implements OnInit {
public allProducts$: Observable<Product[]>;
constructor(private router: Router,
private productService: ProductService) {}
ngOnInit() {
console.log('constructing ProductListComponent');
this.allProducts$ = this.productService.getAllProducts();
}
productDetail(product: Product) {
this.router.navigate([`product/${product.id}`]);
}
}
最后,服务:
import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {API_URL} from '../../app.constants';
import {Product} from '../model/product';
import {first, map} from 'rxjs/operators';
import {BehaviorSubject, Observable} from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ProductService {
constructor(private http: HttpClient) {
}
addProduct(product: Product) {
return this.http.post<Product>(`${API_URL}/product`, product, {observe: 'response'});
}
getAllProducts(): Observable<Product[]> {
return this.http.get<Product[]>(`${API_URL}/product`, {observe: 'response'})
.pipe(map(response => response.body), first());
}
}
很简单的东西。我只是无法让它呈现。所以我尝试在服务中创建一个行为主题并将其订阅到http observable,并将其返回给组件而不是原始的http observable,认为可能组件没有机会及时订阅,如this中所述
接下来,受 this SO question 的启发,我尝试在订阅中手动调用 markForCheck,完全删除异步管道。再一次,什么都没有。
我找不到任何其他解决方案,但这两个是最常见的方法,而且它似乎在任何地方都有效,比如 here or here. Why doesn't it work for me? Clearly, there is something simple eluding me. When I log the response body in the console in the subscription lambda, I can see the product entities I expect from backend, but neither async pipe or subscription in ngOnInit work. I have also seen an approach using
这看起来不对...
<div *ngIf="products.size > 0; else noProducts">
你的意思是:
<div *ngIf="products.length > 0; else noProducts">