google sign-in with angular2 and typescript - where to get gapi?

13,658

Solution 1

Have you included the Google platform API script?

<script src="https://apis.google.com/js/platform.js"></script>

See this question for instructions on how to wait for the GAPI script to load before executing your code.

Solution 2

I also had same problem in Angular v4.0. Removing async defer from the Google platform API script solved my problem

My Problem was like below when I used Google platform api like :

<script src="https://apis.google.com/js/platform.js" async defer></script>

enter image description here

I solved my problem by discarding async defer from Google platform api script as like below in my index.html :

<script src="https://apis.google.com/js/platform.js"></script>
Share:
13,658
NDevox
Author by

NDevox

I'm a Full Stack developer specialising in Python (Django mainly) and JavaScript (React or Angular 2+). I also do a bit of app development using Kotlin. I like to experiment with new languages all the time which is probably when you'll see me on here.

Updated on June 08, 2022

Comments

  • NDevox
    NDevox about 2 years

    I'm trying to use google sign-in with angular2 by following this question: Google Sign-In for Websites and Angular 2 using Typescript

    But I'm getting an error:

    ORIGINAL EXCEPTION: ReferenceError: gapi is not defined
    ORIGINAL STACKTRACE:
    ReferenceError: gapi is not defined
        at LoginAppComponent.ngAfterViewInit (http://localhost:3000/app/login.component.js:33:9)
        at DebugAppView._View_AppComponent0.detectChangesInternal (AppComponent.template.js:46:68)
        at DebugAppView.AppView.detectChanges (http://localhost:3000/node_modules/@angular/core//bundles/core.umd.js:12143:18)
        at DebugAppView.detectChanges (http://localhost:3000/node_modules/@angular/core//bundles/core.umd.js:12247:48)
        at DebugAppView.AppView.detectViewChildrenChanges (http://localhost:3000/node_modules/@angular/core//bundles/core.umd.js:12169:23)
        at DebugAppView.AppView.detectChangesInternal (http://localhost:3000/node_modules/@angular/core//bundles/core.umd.js:12154:18)
        at DebugAppView.AppView.detectChanges (http://localhost:3000/node_modules/@angular/core//bundles/core.umd.js:12143:18)
        at DebugAppView.detectChanges (http://localhost:3000/node_modules/@angular/core//bundles/core.umd.js:12247:48)
        at ViewRef_.detectChanges (http://localhost:3000/node_modules/@angular/core//bundles/core.umd.js:10397:69)
        at eval (http://localhost:3000/node_modules/@angular/core//bundles/core.umd.js:9911:88)
    

    Evidently gapi isn't defined - which I can understand as I seem to only be declaring an empty var.

    My current code is as below:

    import {Component, NgZone} from "@angular/core";
    
    declare var gapi: any;
    
    @Component({
        selector: "login",
        templateUrl: "templates/login-template.html"
    })
    export class LoginAppComponent {
      googleLoginButtonId = "google-login-button";
      userAuthToken = null;
      userDisplayName = "empty";
    
      constructor(private _zone: NgZone) {
        console.log(this);
      }
    
      // Angular hook that allows for interaction with elements inserted by the
      // rendering of a view.
      ngAfterViewInit() {
        // Converts the Google login button stub to an actual button.
        gapi.signin2.render(
          this.googleLoginButtonId,
          {
            "onSuccess": this.onGoogleLoginSuccess,
            "scope": "profile",
            "theme": "dark"
          });
      }
    
      // Triggered after a user successfully logs in using the Google external
      // login provider.
      onGoogleLoginSuccess = (loggedInUser) => {
        this._zone.run(() => {
            this.userAuthToken = loggedInUser.getAuthResponse().id_token;
            this.userDisplayName = loggedInUser.getBasicProfile().getName();
        });
    }
    }
    

    The template loads fine, it is just the gapi bit.

    So my question is: what am I missing? How do I need to be defining gapi for it to work?

    Here is my main app.component code:

    import { Component } from '@angular/core';
    import { LoginAppComponent } from './login.component'
    
    @Component({
      selector: 'my-app',
      template: `<script src="https://apis.google.com/js/platform.js?onload=onLoadCallback" async defer></script>
                <script>
                window.onLoadCallback = function(){
                  gapi.auth2.init({
                      client_id: 'filler_text_for_client_id.apps.googleusercontent.com'
                    });
                }
                </script>
                 <h1>Angular2 P.O.C.</h1>
                 <login></login>`,
      directives: [LoginAppComponent]
    })
    export class AppComponent { }
    
  • NDevox
    NDevox almost 8 years
    Hi, thanks for the response! Can you be a bit more detailed? JS/TS with angular is definitely a weak spot for me. I went through the question and added it to my main app template - not the prettiest solution. It still isn't working though and I'm not entirely sure if what I did was right - or how to correct it.
  • rphv
    rphv almost 8 years
    This question provides a couple of strategies for using the Google API with Angular. It sounds like you're encountering a condition where Angular tries to access the gapi object before the platform.js script is loaded. Instead of adding the <script> tag to your app template, can you load platform.js along with the Angular core, e.g. in the html where you declare ng-app?
  • NDevox
    NDevox almost 8 years
    It works now thanks! I was also missing the google-signin-client-id meta header.
  • Insane Rose
    Insane Rose over 7 years
    @Scironic I tried it but it didn't work. Can you help me by sending code? <3
  • Assaf S.
    Assaf S. almost 7 years
    Removing async defer in NG 4 solved my problem. Thank you!
  • Muhammed Ozdogan
    Muhammed Ozdogan about 5 years
    Thank you very much Amir :)