Angular, проблема с использованием ngIf, async и Observable для ожидания готовности данных для отображения содержимого - PullRequest
0 голосов
/ 10 октября 2018

Я новичок в Angular и застрял.Я не могу заставить это работать, и я думаю, что я просто делаю некоторые ошибки в том, как я реализую Observable.В настоящее время я использую локальный файл json в качестве источника данных, но в моем основном проекте я подключусь к внешнему API.Я сократил все, чтобы сделать его как можно более простым, но все же не повезло.

Вот рекламный файл campaign.component.ts

    import { Component, OnInit } from '@angular/core';

    import { Observable } from 'rxjs';

    import { CampaignService } from '../campaign.service';

    @Component({
      selector: 'app-campaign',
      templateUrl: './campaign.component.html',
      styleUrls: ['./campaign.component.css']
    })
    export class CampaignComponent implements OnInit {

    $campaign: Observable<any>;

      constructor(
        private campaignService: CampaignService
      ) {}

      ngOnInit(): void {
        this.getCampaign();
      }

      getCampaign(): void {
        this.campaignService.getCampaign().subscribe((data) => {
          this.$campaign = data;
          console.log(this.$campaign);
        });
      }
    }

Вот шаблон html, campaign.component.html

    <div *ngIf="($campaign | async) as campaign; else loading">
    <!--this never loads-->
      {{campaign.shortName}}
    </div>

    <ng-template #loading>
    <!--this is all I see-->
      Loading stuff in ngIf...
    </ng-template>

    <br>
    <br>
    <!--this works so I know the data loads and that my json file is formatted correctly-->
    <p>Outside of ngIf works: {{$campaign.shortName}}</p>

Вот сервис, campaign.service.ts

    import { Injectable } from '@angular/core';
    import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
    import { Observable, of } from 'rxjs';
    import { map} from 'rxjs/operators';

    const endpoint = 'assets/api.json';

    const httpOptions = {
      headers: new HttpHeaders({
        'Content-Type':  'application/json'
      })
    };

    @Injectable()
    export class CampaignService {

      constructor(private http: HttpClient) {}

      private extractData(res: Response) {
        let body = res;
        return body || { };
      }

      getCampaign(): Observable<any> {
        const url = endpoint;
        console.log(url);
        return this.http.get(url).pipe(
          map(this.extractData));
      }

    }

Спасибо, что нашли время помочь с этим.

1 Ответ

0 голосов
/ 10 октября 2018
  getCampaign(): void {
    this.campaignService.getCampaign().subscribe((data) => {
      this.$campaign = data;
      console.log(this.$campaign);
    });
  }

Вышеприведенное присваивает значение данных свойству this.$campaign, но вы объявили это свойство наблюдаемым.

<div *ngIf="($campaign | async) as campaign; else loading">
<!--this never loads-->
  {{campaign.shortName}}
</div>

$ кампания не являетсянаблюдаемый, поэтому асинхронный канал разрешается неопределенным.Условие всегда false .

<!--this works so I know the data loads and that my json file is formatted correctly-->
<p>Outside of ngIf works: {{$campaign.shortName}}</p>

Вышеуказанное работает, потому что $ campaign было присвоено значение данных.

<p>Outside of ngIf works: {{($campaign | async)?.shortName}}</p>

Вы должнывсегда используйте async в шаблоне для наблюдаемых.

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

  constructor(private campaignService: CampaignService) {
      this.$campaign = campaignService.getCampaign(); 
  }

В качестве альтернативы, вам не нужно использовать async если вы подписываетесь и назначаете данные.

<div *ngIf="campaign; else loading">
<!--this never loads-->
  {{campaign.shortName}}
</div>

<p>Outside of ngIf works: {{campaign?.shortName}}</p>
...