Шаблон не отображает наблюдаемый при использовании асинхронного канала - PullRequest
1 голос
/ 12 марта 2019

Я только начинаю с угловых, и после попытки понять себя, что происходит, я просто не смог найти решение. У меня есть простой шаблон:

<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>

С классом:

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 и вернуть ее компоненту вместо исходной наблюдаемой http, думая, что, возможно, компонент не имел возможности подписаться вовремя, как упоминалось в этой статье. SO . Неудачно.

Затем, вдохновленный этим SO вопросом , я попытался вручную вызвать markForCheck в подписке, полностью удалив асинхронный канал. Опять ничего.

Мне не удалось найти никакого другого решения, но эти два являются наиболее повторяющимися подходами, и везде, где это только кажется, работает, как здесь или здесь . Почему это не работает для меня? Очевидно, что что-то простое ускользает от меня. Когда я регистрирую тело ответа в консоли в лямбда-подписке, я вижу объекты продукта, которые ожидаю от бэкэнда, но ни асинхронный канал, ни подписка в ngOnInit не работают. Я также видел подход, использующий ngZone.run , но у меня такое ощущение, что можно было бы просто выполнить то же самое, что и обычная подписка и markForCheck.

1 Ответ

3 голосов
/ 12 марта 2019

Это выглядит не так ...

<div *ngIf="products.size > 0; else noProducts">

Вы имеете в виду:

<div *ngIf="products.length > 0; else noProducts">
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...