1

I'm using a few REST services to gather data and then change the value of an Observable in my component code. I'm trying to use an *ngIf to show/hide div tags based on the result. However, it isn't working, the *ngIf is not updating based on the change to the Observable.

Do I have to trigger change detection? What's the best way to achieve this in Angular 7? Here's one example I tried:

HTML:

<div *ngIf="isAnimal$">
     <p>animal</p>
</div>

Component:

public isAnimal$: Observable<boolean> = of(false);
...
ngOnInit() {
  checkAnimal();
}

private checkAnimal() {
  this._dataService.getData()
      .subscribe((result) => {
         if (result === 'animal') {
           this.isAnimal$ = of(true);
         }
      });
}

I also tried creating a simple service and that didn't work either. Like this: Angular *ngIf binding to function

beachCode
  • 3,202
  • 8
  • 36
  • 69

1 Answers1

4

I suggest the following:

HTML:

<div *ngIf="isAnimal">
     <p>animal</p>
</div>

Component:

public isAnimal: boolean = false;

ngOnInit() {
  checkAnimal();
}

private checkAnimal() {
  this._dataService.getData().subscribe(
    (result) => {
       if (result === 'animal') {
         this.isAnimal = true;
       }
    },
    (error) => {
      console.log(error);
    }
 );
}

I am not sure, but I think you could use the async pipe instead using your implementation:

<div *ngIf="isAnimal$ | async">
     <p>animal</p>
</div>

The reason your solution is not working is because isAnimal$ is an observable that has to be resolved. The async pipe could do this, but I prefer the first solution to be honest. It does not seem natural to me to create another observable of(true) in your subscription.

andreas
  • 7,844
  • 9
  • 51
  • 72
  • that's the first approach I tried. I'm logging the result: "animal : true" but the *ngIf isn't changing the HTML. I suspect the *ngIf is not waiting for the async call to return. The async pipe doesn't work with a boolean. – beachCode Nov 27 '18 at 01:05
  • @beachCode the first approach works for 100 %, the *ngIf automatically listens to the changes of the value that is passed, which is a boolean. The second approach should work as well. Don't forget that `isAnimal$` is not a boolean here, it is an observable. When it is resolved, it should be a boolean. – andreas Nov 27 '18 at 01:17
  • I just noticed something weird. I am using interpolation to show some data ({{name}} and that isn't updating either.... weird. What's up with this component? – beachCode Nov 27 '18 at 01:38
  • so the issue here seems to be an error that's caused by a Google API call. I couldn't see it initially but it appeared when I changed the component behaviour. The error appears to be causing the issues I'm seeming with interpolation and *ngif not working. Here's the first part of the error from the console: ERROR DOMException: Failed to execute 'querySelector' on 'Document': '#scope=openid email profile https://www.googleapis.com – beachCode Nov 27 '18 at 07:03
  • 1
    You should always add error handling when you subscribe (see my edits above), this might help to find the issues. :) – andreas Nov 27 '18 at 13:03