Search code examples
angulargoogle-oauth

angular2 binding not working with google oauth2 promise


Everything works as expected BUT I cannot get the view to update.

I would expect the subscription inside ngOnInit() to update the view each time data comes down the stream.

However, whilst data is coming down the stream, the code this.user = user does not update the view :(

My component code is ...

import {Component, OnInit} from '@angular/core';
import {Subject, Observable} from 'rxjs/Rx';
import {AuthService} from '../../../services/auth.service';
import 'rxjs/add/operator/catch';
declare let auth2:any;

@Component({
  selector: 'user',
  templateUrl: 'build/routes/app/user/user.component.html',
  styleUrls: ['build/routes/app/user/user.component.css'],
  providers: [AuthService]
})

export class UserComponent implements OnInit {

  private userSubject = new Subject<string>();
  public user:any;

  public userStream:Observable<any> = this.userSubject.asObservable().flatMap((code:any) => {
    let restStream = this.authService.signIn(code)
      .map((response:any) => {
        return JSON.parse(response._body);
      }).catch((err:any) => {
        return Observable.throw(err);
      });
    return restStream;
  }).publish().refCount();

  constructor(public authService:AuthService) {
  }

  ngOnInit() {
    this.userStream.subscribe((user:any) => {
      console.log(user); // user is set
      this.user = user; // this does not update the view :(
    });
  }

  public googleSignIn() {
    auth2.grantOfflineAccess({'redirect_uri': 'postmessage'}).then((authResult:any) => {
      this.userSubject.next(authResult.code);
    });
  }

}

view is simply ...

<button (click)="googleSignIn()">Google Sign In</button>
<div>USER = {{user | json}}</div>

How do I get Angular2 to update the view?

Note: the global declaration auth2 refers to global Google OAuth2 - thanks


Solution

  • Let confirm if this.user is being set by adding another console log in subscribe.

    console.log(this.user);
    

    I think it would be set but UI is not updating is your issue. Just for starter you can try wrapping the user set in timeout and see if UI updates like

    setTimeout( user => this.user = user, 0);
    

    If this gets you working then your a setting the variable too early/too late for change detection to pick up.

    setTimeout is not an ideal way to achieve this so we should refactor your code in appropriate way to ensure angular2 change detection picks up the changes. If this gets you working post more details about the template or put up a plunker and we can see what could be a better way to achieve.