0
votes

I was trying to load a child component based on data that will retrieve by HTTP get call. I was using a service to do the HTTP call and subscribing on the component's constructor. But the ngif was calling before the data retrieve.

so i have applied async pipe in the ngif but it is triggering another error.

service code:

GetContest(id){
    return this.http.get(this.baseurl+id);
}

constructor of component:

this.service.GetContest(this.route.snapshot.paramMap.get('id')).
    subscribe( (res)=> {
      this.contest = res;
      console.log(this.contest);
    });

template ngif:

<app-beforecontest *ngIf="contest.startTime<date "></app- 
beforecontest>

above codes generate an error:

TypeError: Cannot read property 'startTime' of null

and after this I joined async pipe like this:

<app-beforecontest *ngIf="(contest|async).startTime<date "></app- 
beforecontest>

and it is generating an error:

ContestComponent.html:1 ERROR Error: InvalidPipeArgument: '[object 
Object]' for pipe 'AsyncPipe'
at invalidPipeArgumentError
3
The async pipe works on observables, it's unclear why you expected it to work like that.jonrsharpe

3 Answers

1
votes

The async pipe needs to be used on an observable, I created a simple stackblitz to show it: https://stackblitz.com/edit/angular-tx7g36

The main code you need to change is in the component itself

import { Component } from '@angular/core';
import {ContestService} from './contest.service';
import {Observable} from 'rxjs';

@Component({
  selector: 'my-app',
  template: `
    <h1>Contest startTime</h1>
    <p>{{(contest$ | async)?.startTime}}</p>
  `,
})
export class AppComponent  {
  contest$: Observable<any>;

  constructor(private contestService: ContestService) {
    this.contest$ = this.contestService.getContest();
  }
}

In case you wonder about the $ at the end of the contest property, that's a notation to distinguish an observable from other types of data.

0
votes

You can set the initial value of this.contest to null in your component.ts

this.contest = null

and in template check it like this:

<app-beforecontest *ngIf="contest?.startTime < date"></app- 
beforecontest>

@jonrsharpe Thanks for clearing this out

note that startTime<date "> is a VERY wierd string and I don't know what you mean here.

In general, if you want to use the async pipe you should use it on Observable:

myObservable$ = this.service.GetContest(this.route.snapshot.paramMap.get('id'));

as you can see we did NOT .subscribe to it (!!!)

and in template first async the observable and then add .startTime

<app-beforecontest *ngIf="(myObservable$ | async).startTime < date"></app-beforecontest>
-1
votes

In case of handling the async response and binding the template you could use safe naviagation operator as well like this -

<app-beforecontest *ngIf="contest?.startTime<date "></app- 
beforecontest>

Otherwise If you want to use async pipe you have to use it like below mannet -

<app-beforecontest *ngIf="contest.startTime | async"></app-beforecontest>

PS: But here in your case contest is not of asnyc in nature, you are just assigning it to value which is coming from async request. So better to use safe navigation operator ?.