Angular 2 View will not update after variable change in subscribe
TypescriptAngularTypescript Problem Overview
I have a problem where my view will not change when I update my variable in my observable subscription. I am trying to show a loading spinner while I wait for a response from my backend and then display the response, but the spinner won't hide. My subscription looks like this:
this.isRequesting = "true";
this.questionService.onSubmit(form, this.questions).subscribe( (value) => {
this._ngZone.run( () => {
this.fileLocation = JSON.stringify(value);
console.log(this.fileLocation);
this.isRequesting = "false";
console.log(this.isRequesting);
});
});
And my html for this component looks like this:
<spinner *ngIf="isRequesting=='true'"></spinner>
I can see that isRequesting changes to "false" in my console after I get a response back from the backend (Springboot), but the view still does not change. The spinner was from SpinKit and I modified this tutorial for my spinner to work.
I have tried:
- The way in the tutorial (with stopRefreshing() in the error and complete parameters of the observable)
- ngZone to force my view to update.
Does anyone have any ideas on how to get my view to update or any way to get my spinner to hide after I get a response from my backend?
Typescript Solutions
Solution 1 - Typescript
are you seeing any error on console?
This could be due to fact that angular is not running change detection after you have made updates to value.
I think you don't need ngZone.run
as it will run code outside the angular zone.
this.questionService.onSubmit(form, this.questions).subscribe( (value) => {
this.fileLocation = JSON.stringify(value);
console.log(this.fileLocation);
this.isRequesting = "false";
console.log(this.isRequesting);
});
If due to some reason you need to run this outside Angular zone, then you should inform angular to run a change detection cycle by either of this method.
-
just wrap update of isRequesting in set timeout
setTimeout( () => this.isRequesting = "false", 0);
-
invoking change detection manually
import {ChangeDetectorRef} from '@angular/core' constructor(private ref: ChangeDetectorRef){} this.questionService.onSubmit(form, this.questions).subscribe( (value)=> { //existing code console.log(this.isRequesting); this.ref.detectChanges(); });
Solution 2 - Typescript
You can also try this solution: Guide from Thoughtram
Short version:
import { ChangeDetectorRef } from '@angular/core';
...
constructor(private cd: ChangeDetectorRef) {}
...
... .subscribe( () => {
<yourstuff>
this.cd.markForCheck();
}
and you are good.
Background: when changing a value via .subscribe() angular does not notify that it should run changedetection. So you need to run it yourself.
Solution 3 - Typescript
You can switch (on/off) template updating via changeDetection. You have to put your choice of strategy into component definition. You can choose Default or OnPush strategy.
@Component({
selector: '...............',
templateUrl: '.......html',
styleUrls: ['..........scss'],
changeDetection: ChangeDetectionStrategy.Default
})
Solution 4 - Typescript
if you are using it in expression *ngIf
remember *ngIf = false
will not work as expression you need to add
<ul *ngIf=" somefunction(x) ? false: true">