Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular Js and google api client.js (gapi)

It took me one day to make it works so I think my experience may be useful from someone. And maybe some others will find improvement.

So I start angularJS two days ago. And I want it works with Google Cloud Endpoints to create a backend interface. Here comes the trouble for me.

The javascript client for gapi comes with asynchronous loading, so angular initialization will crash having gapi undefined.

So you need to bootstrap angular when gapi is initialized:

  1. remove ng-app="myApp"
  2. Add <script src="https://apis.google.com/js/client.js?onload=googleOnLoadCallback"></script>
  3. Add the callback:

    function googleOnLoadCallback(){       var apisToLoad = 1; // must match number of calls to gapi.client.load()       var gCallback = function() {           if (--apisToLoad == 0) {               //Manual bootstraping of the application               var $injector = angular.bootstrap(document, ['myApp']);               console.log('Angular bootstrap complete ' + gapi);           };       };       gapi.client.load('helloWorld', 'v1', gCallback, '//' + window.location.host + '/_ah/api');   } 

Feel good but how about a call ?

So here is the controller:

angular.module('myApp.controllers', []).       .controller('MyCtrl', ['$scope' ,'helloWorldService',           function($scope,greetingsService) {           helloWorldService.loadData($scope);       }]); 

And here is the service:

angular.module('myApp.services', []) service('helloWorldService', [function() {    this.loadData = function($scope)  {      //Async call to google service      gapi.client.helloWorld.greetings.listGreeting().execute(         function(resp) {             if (!resp.code) {                 console.debug(resp);                 $scope.greetings = resp.items;                 // Because it's a callback,                 // we need to notify angular of the data refresh...                 $scope.$apply();             }       });    }; }]); 

And magically your page updates thanks to angular.

Feel free to mark anywhere I go wrong.

like image 829
Samuel Avatar asked Oct 16 '13 09:10

Samuel


People also ask

What is gapi JS?

GAPI is Google's client library for browser-side JavaScript. It's used in Google Sign-in, Google Drive, and thousands of internal and external web pages for easily connecting with Google APIs.

Is angular js an API?

The AngularJS Global API is a set of global JavaScript functions for performing common tasks like: Comparing objects. Iterating objects. Converting data.


2 Answers

Rather than bootstrapping or setting a timeout, it's most efficient to let Angular load before/while you're making the server requests. I followed the advice described in AngularJS + Cloud Endpoints: A Recipe for Building Modern Web Applications, which does the following.

Keep your ng-app directive as usual (no bootstrapping)

<html ng-app="myApp"> <head>   <script src="angular.js" type="text/javascript"></script>   <script src="app.js" type="text/javascript"></script>   <script src="https://apis.google.com/js/client.js?onload=init"></script> </head> <body ng-show="backendReady"> 

Create a global variable for the GAPI callback function anywhere in your JS

var app = angular.module('myApp', []);  var init = function() {   window.initGapi(); }  app.controller('MainController', function($scope, $window, gapiService) {   var postInitiation = function() {     // load all your assets   }   $window.initGapi = function() {     gapiService.initGapi(postInitiation);   } });  app.service('gapiService', function() {   this.initGapi = function(postInitiation) {     gapi.client.load('helloWorld', 'v1', postInitiation, restURL);   } }); 

From link above:

The reason why you would not want to execute the initialization in the first init() method is so you can put as much of the code as possible in the AngularJS world, such as controllers, services and directives. As a result, you can harness the full power of AngularJS and have all your unit tests, integrations tests,and so forth.

This may seem like a roundabout way of doing things, but it optimizes for speed, testability, and separation of concerns.

like image 113
willlma Avatar answered Sep 23 '22 12:09

willlma


Nice post and thanks! This approach worked for me. It might matter what order that the code appears in your index.html file. It did not work for me until I had things inthis order.

... <script>   function googleOnLoadCallback(){       alert('googleOnLoadCallback called');       var apisToLoad = 1; // must match number of calls to gapi.client.load()       var gCallback = function() {           if (--apisToLoad == 0) {               //Manual bootstraping of the application               var $injector = angular.bootstrap(document, ["myApp"]);               console.log("myApp bootstrap complete " + gapi);           };       };       gapi.client.setApiKey("my_client_id");       gapi.client.load("translate", "v2", gCallback);    } </script> <!-- See https://developers.google.com/api-client-library/javascript/samples/samples --> <script src="https://apis.google.com/js/client.js?onload=googleOnLoadCallback"></script> </head> 
like image 29
davedonohue Avatar answered Sep 21 '22 12:09

davedonohue