Observable with Async Pipe in template is not working for single value

angular async observable
angular async pipe promise
angular async pipe without *ngif
the pipe 'async' could not be found
angular observable in template
ngmodel async pipe
angular async pipe null
angular http async pipe

I have a component which asks my service for an Observable object (that is, the underlying http.get returns one single object).

The object (an observable) is used in conjunction with an async pipe in my template. Unfortunately I get an error:

Cannot read property 'lastname' of null

I have been breaking my head on this one. A similar type of code works correctly on a list of object (in conjunction with *ngFor).

 <li>{{(person | async)?.lastname}}</li>

Method in my service:

  ....
  getPerson(id: string): Observable<Person> {        
     let url = this.personsUrl + "/" + id;
     return this.http.get(url, {headers: new Headers({'Accept':'application/json'})})
                .map(r => r.json())
                .catch(this.handleError); //error handler
  }
  ....

In my component:

//... imports ommitted

@Component({
  moduleId: module.id,
  selector: 'app-details-person',
  templateUrl: 'details-person.component.html',
  styleUrls: ['details-person.component.css'],
})
export class DetailsPersonComponent implements OnInit, OnDestroy {

   person: Observable<Person>;
   sub: Subscription;

   constructor(private personService: PersonService, private route: ActivatedRoute) {
   }

  ngOnInit() {
     this.sub = this.route.params.subscribe(params => {
                 let persId = params['id'];
                 this.person = this.personService.getPerson(persId);
                });
  }

  ngOnDestroy(): void {
     this.sub.unsubscribe();
  }
}

Apparently the observable is/returns a null object value in the pipe. I have checked if I am really getting a nonempty Observable from my service and I can confirm that there exist an (underlying) object returned from my service.

Of course I could subscribe to the observable in my component after having retrieved the Observable from the service, but I would really like to use the async construct.

Btw, other question: Is there already a pattern how to handle errors which occur in the async pipe? (A downside of using async pipes.... errors are delayed until rendering time of the view.

The first time your view renders, person is not defined, since that component property only gets created asynchronously, when the route params subscription fires. You need to initially create an empty observable. Instead of

person:Observable<Person>;

try

person = Observable.of<Person>(Person());  // or however you create an empty person object
    // the empty object probably needs a lastname field set to '' or null

I normally handle errors in a service by

  1. return an empty observable
  2. report the error to some app-wide (singleton) service. Some (singleton) component then displays those errors (if appropriate) somewhere on the page.

Async Pipe: How to use it properly in Angular, The angular async pipe allows the subscription to observables inside of the angular template syntax. It also takes care of unsubscribing from observables automatically. Let's take a look at an example. This component To do that, the observable has to resolve to an array type, not just a single value. How to use the async pipe with *ngForIn the same way we can use the async pipe with the ngIf directive, we can use it with the ngFor directive. To do that, the observable has to resolve to an array type, not just a single value.

Please try to change the line

person:Observable< Person>

into

person:Observable< any>;

If that does not work , print out this {{ person | async | json }} please with the change above of course and see what you get.

Handling Observables with NgIf and the Async Pipe, Everytime we use the async pipe, we create a subscription. ngIf alongside the async pipe to alleviate some of these common issues. We'll refactor this component's template before we finish with some What this will do is wait until user$ | async has evaluated, and bind the result to the value of user  Our friend NgIf has a not-so-obvious feature that lets us will help us deal with asynchronous operations - via the async pipe takes care of subscribing to Observable streams for us. There are a few common gotchas when dealing with purely cold Observables that somewhat pull in data (over perhaps, Http).

AsyncPipe, Input valuelink The async pipe subscribes to an Observable or Promise and returns the latest value it This example binds a Promise to the view. template: '<div><code>observable|async</code>: Time: {{ time | async }} One framework. Observable: This is a stream of events that can be processed with array-like operators. Every HTTP service method returns an Observable. Promise: It is a proxy for a value not necessarily known when the promise is created. It does not return immediately a final value. It returns a promise to supply the value at some point in the future.

This can occur if you use a Subject<T> observable as opposed to a ReplaySubject<T> or BehaviorSubject<T>.

What happens with a Subject<T> is that it 'broadcasts' its value only one time to whatever listeners are registered at that time.

So if you call next('hello word') on an observable message: Subject<string> it can only update the UI if that 'piece' of UI exists at that moment in time.

So in this example the message won't appear - unless you call next twice!

<div *ngIf="message | async">
   here is the message {{ message | async }}
</div>

The easiest solution is to use a ReplaySubject<string>(1) where 1 is the number of values it remembers (we only want one here).

subscribe() vs, the way | async pipe works for the collection vs for singular objects; possibility of Simple example of consuming observable stream of todos by unwrapping it in Case 2: Use | async pipe in the component template like this <dumb [prop]="​value$ | async"></dumb> so you have working OnPush while  Manner 1: We subscribe to an observable in our template using the async pipe. The benefit of this is that Angular deals with your subscription during the lifecycle of a component.

Angular Reactive Templates with ngIf and the Async Pipe, Angular Reactive Templates with ngIf and the Async Pipe type of Observables we use); more readable code; less potential issues with multiple This approach works great, but one potential issue is that now we have to inside the ngIf section, that corresponds to the value emitted by the backend call  Angular Reactive Templates with ngIf and the Async Pipe Last Updated: 24 April 2020 local_offer Angular Core The ngIf template syntax is very useful in many common use cases, like for example using an else clause when we want to display a loading indicator.

Value change in observable subscription not triggered in async pipe , GitHub is home to over 50 million developers working together to host and review code Value change in observable subscription not triggered in async pipe #​21584 The change can be seen in the dumb component as soon as one changes the value. inside template via async pipe: http://plnkr.co/edit/  Using *ngIf and the async pipe we can unwrap each Observable into a single value object that contains the unwrapped value of each Observable. This use of *ngIf is not a well-known ability of the Angular template syntax but allows an easy way to subscribe to multiple Observables in our template as well as reference to it numerous times.

Using the Async Pipe in Angular, The async pipe in angular will subscribe to an Observable or Promise and return the latest value it has emitted. Now let's see an example where we are binding a Promise to the view. 21 22 23 24 25 26 27 28 29 30 @Component({ selector: 'async -pipe', template: `<div> <code>promise|async</code>:  Async pipelink. The AsyncPipe subscribes to an observable or promise and returns the latest value it has emitted. When a new value is emitted, the pipe marks the component to be checked for changes. The following example binds the time observable to the component's view. The observable continuously updates the view with the current time.

Comments
  • This should work. Please show your service code that returns the observable, and your component code that defines person. Or better, create a plunker.
  • Hi Mark, I have updated the question section above. You may read a fragment of the service and the component code above. Thanks.
  • Hi Mark, thanks for the reply. Indeed, I agree about the asynchronous behaviour with respect to person and route params code. I followed your suggestion but I still see the same error. It seems as if the view is rendered before person is defined (with a service call). Am I in a wrong life cycle?
  • If person = Observable.of<Person>(Person()); is defined before your constructor, it should exist when the view is first rendered. You can test this by commenting out your this.person = ...` code.
  • Hi Mark, Done that (before), but in vain. This one is a brain wrecker :-( I am starting to think whether I ve an issue with libraries and compatibility. As you said before... this should work. Straight forward but still an issue.
  • Did you try flatMap instead of map?