Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

angular 4 variable not updating the first time

Here is the problem I am facing.

I have a variable inside a component which assigned to a directive. I am using ngrx to dispatch and susbcribe to events. So the problem is that the variable does not update the first time. After that there is no problem.

I have a google map and icons on it and on click of any icon it makes a call to the server with the id and map bounds and then with the returned data an action is dispatched.

private getFromServer(id, bound_corners){
    let params = { bounds: bound_corners }
    return this.restangular.all('get-data/'+id)
            .customGET("", params)
            .map((d:any)=>{
                return d.plain();
            });
}

public onClick(icon){
    let bound_corners = this.getMapBounds();

    this.getFromServer(icon.id, bound_corners).subscribe((d)=>{

        this.store.dispatch(new action.detail(d, id));

    });
}

In the component class

let temp = store.select(fromRoot.getIconDetail);

temp.subscribe((d)=>{
    this.data = d;
})

In the component this.data does not get updated the first time. If I console log(this.data) then it works but it does not get updated in the html.

If I take the dispatch action out of the getFromServer subscription like this:

public onClick(icon){
    let bound_corners = this.getMapBounds();

    let temp_data = {name:"test","id":0};

    this.store.dispatch(new action.detail(temp_data, id));
}

then it works.

Currently I have one solution which is using ChangeDetectorRef.

constructor(private chRef: ChangeDetectorRef){

    let temp = store.select(fromRoot.getIconDetail);

    temp.subscribe((d)=>{
        this.data = d;
        this.chRef.detectChanges();
    });
}

I am not sure if this is the right way but I am unable to figure out whats going on or any other solution.

Any help will be greatly appreciated. Thanks

like image 880
sushmit sarmah Avatar asked Feb 13 '26 17:02

sushmit sarmah


1 Answers

Maybe instead of assigning the subscription to a variable, execute it directly.

constructor(){

store.select(fromRoot.getIconDetail)
    .subscribe(d => {
          this.data = d;
    })

}

It's worth noting that when you use .subscribe, you need to unsubscribe when the component is destroyed, or you'll wind up accumulating multiple subscribes on the Observable when the component is revisited and reloaded.

To prevent this, and to prevent memory leaking, you should unsubscribe to the Observable when you destroy each component.

Add these imports to your component

import 'rxjs/add/operator/takeUntil';
import { Subject } from 'rxjs/Subject';

Add this in your class - I usually do this above the constructor.

  private ngUnsubscribe: Subject<any> = new Subject<any>()

Add an ngOnDestroy function

  ngOnDestroy() {
    this.ngUnsubscribe.next();
    this.ngUnsubscribe.complete();
  }

And then add this immediately before your .subscribe (you should use this exact syntax before every .subscribe in components with multiples).

  .takeUntil(this.ngUnsubscribe)

So in your case, it would look like this.

constructor(){

store.select(fromRoot.getIconDetail)
    .takeUntil(this.ngUnsubscribe)
    .subscribe(d => {
          this.data = d;
    })

}

So what happens is the subscribe will remain active until you navigate away from the component, at which point ngOnDestroy fires which unsubscribes from the Observable cleanly.

like image 57
Stephen R. Smith Avatar answered Feb 16 '26 06:02

Stephen R. Smith



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!