Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

angular change detection for updates within a callback

I am looking for reasoning about a simple problem. I have a simple component which has a boolean property which i display in the component's template.Now the problem is that if I update this property in a callback, the property does get updated (in the component) but the updated value does not get rendered (change detection does not work, and I have to explicitly call changeDetectorRef.detectChanges(); to render the updated value).

I have this in my template:

<div *ngIf="isUserLoggedIn">
      <router-outlet></router-outlet>
</div>
<div *ngIf="!isUserLoggedIn">
    <div id="googleBtn" (click)="onSignIn()">Sign In</div>
</div>

and this in my component:

gapi.load('auth2', () => {
      this.auth2 = gapi.auth2.init({
        client_id: '769107420471-782b0i2f3dt9u05dhrb4j21g7ajglrg6.apps.googleusercontent.com',
        cookiepolicy: 'single_host_origin',
        scope: 'profile email'
      });
      var googleBtn = document.getElementById('googleBtn');
      if(googleBtn) {
        this.attachSignin(document.getElementById('googleBtn'));
      }
    });
  }
  public attachSignin(element) {
    this.auth2.attachClickHandler(element, {},
      (googleUser) => {
        this.signUpService.googleLogin(googleUser.getAuthResponse().id_token, 
        this.successCallback.bind(this), 
        this.signOut.bind(this));
      }, (error) => {
        alert(JSON.stringify(error, undefined, 2));
      });
  }

  successCallback = function (data) {
    // this.changeDetectorRef.detectChanges();
    this.isUserLoggedIn = this.utils.isUserLoggedIn();
  }

as you can see the expected behaviour is : initially "isUserLoggedIn" will be false, and then user clicks on "Sign In" button, which calls a function from another service and toggles "isUserLoggedIn" in the successCallback of that function thus resulting in the template elements also getting toggled.

But this only happens if I uncomment the first line in successCallback (), my quest is why do I need to explicitly call changeDetectorRef.detectChanges() to reflect changes in dom, why change detection is not working with callback (I checked other wise, with simple Observable.interval(2000).subscribe(x => {this.isUserLoggedIn = !this.isUserLoggedIn}); which works perfectly fine)

like image 201
FreakAtNs Avatar asked Sep 18 '17 16:09

FreakAtNs


1 Answers

It doesn't work because load event callback is triggered outside of Angular zone. You can fix it like this:

constructor(private zone: NgZone) {}

gapi.load('auth2', () => {
    zone.run(() => {
        this.auth2 = gapi.auth2.init({
            client_id: '769107420471-glrg6.apps.googleusercontent.com',
            cookiepolicy: 'single_host_origin',
            scope: 'profile email'
        });
        var googleBtn = document.getElementById('googleBtn');

For more information read:

  • Do you still think that NgZone (zone.js) is required for change detection in Angular?
like image 71
Max Koretskyi Avatar answered Oct 27 '22 03:10

Max Koretskyi