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:
- remove ng-app="myApp"
- Add
<script src="https://apis.google.com/js/client.js?onload=googleOnLoadCallback"></script>
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.
I used a solution similar to willlma, but my application makes use of UI Router, so there's no knowing which controller will be called.
I was able to solve this with a Javascript Promise.
index.html
app.js
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.
So I was having the same problem. Putting this code in my factory worked
Basically, the problem is trying to call gapi.client before it loaded. If you just check that it's loaded, and if it isn't then try again in a second (you can set the time for whatever you want, set it lower if you expect the user to need this relatively quickly after the page loads).
I was struggling with this for a while, and this is all that worked for me...Hope this helps!
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)Create a global variable for the GAPI callback function anywhere in your JS
From link above:
This may seem like a roundabout way of doing things, but it optimizes for speed, testability, and separation of concerns.
I wrote a simple directive to load the google map API asynchronously :
Then in your main controller, you can handle the event :
You just have to declare the directive in your body tag :
Although pretty much on progress maybe also worth to mention angular-googleapi, which wraps nicely some Google Calendar and Google Plus API calls and easy extendable.
You'd need to add this bit to your controller when checking for authorisation: