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)
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:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With