I\'m new to AnuglarJS and already built a small web-app with it, I would like to use the Facebook JavaScript SDK with it, but using best practices (dependency injecting to contr
I have actually had to do this... I don't have the code with me, and it's probably proprietary anyhow... but it was essentially like this:
// create a simple factory:
app.factory('facebook', ['$window', function($window) {
//get FB from the global (window) variable.
var FB = $window.FB;
// gripe if it's not there.
if(!FB) throw new Error('Facebook not loaded');
//make sure FB is initialized.
FB.init({
appId : 'YOUR_APP_ID'
});
return {
// a me function
me: function(callback) {
FB.api('/me', callback);
}
//TODO: Add any other functions you need here, login() for example.
}
}]);
// then you can use it like so:
app.controller('SomeCtrl', function($scope, facebook) {
//something to call on a click.
$scope.testMe = function() {
//call our service function.
facebook.me(function(data) {
$scope.facebookUser = data;
//probably need to $apply() this when it returns.
// since it's async.
$scope.$apply();
});
};
});
If there are any errors in that let me know, and I'll look up the working code I have and see what I've missed. But that should be about it.
I have written this angularjs-facebook service. First you init it on your app module config method to initialize your facebook app id and other settings.
Then you just enjoy calling the Facebook service from Controllers and calling Facebook methods asynchronous just as normal.
https://github.com/ciul/angularjs-facebook
I was stumped on this for a while, I solved it with a $watch
//setup watch for FB API to be ready
//note that since you use $window, you need to inject it into your controller
//angular.module('myApp').controller('appController', function ($scope, $window, ...) {
$scope.FBListener = $scope.$watch(function () {
return $window.FB;
}, function (newVal, oldVal) {
// FB API loaded, make calls
console.log("FB is ready");
//functions that do FB API calls
$scope.getFBEvents();
$scope.getFBPosts();
});
when FB has been loaded, you can clear the $watch (which is probably best to do for performance) by calling $scope.FBListener();
2015 EDIT !
This is an old answer. I'll suggest you check out how the popular angular-modules on github do it or simply use them:
Old Answer
Because of problems with calls at the start of the app I use the following approach, which loads the app only after the SDK has been loaded:
window.fbAsyncInit = function () {
FB.init({
appId: window.fbConfig.appID,
channelUrl: '//' + window.location.hostname + window.location.pathname + 'channel.php',
status: window.fbConfig.oInitOptions.bStatus || true,
cookie: window.fbConfig.oInitOptions.bCookie || true,
xfbml: window.fbConfig.oInitOptions.bXfbml || true
});
// Get Login Status once at init
window.FB.getLoginStatus(function (oResponse) {
if (oResponse && oResponse.status) {
window.fbConfig.sAuthStatus = oResponse.status;
}
// Bootstrap app here only after the sdk has been loaded
angular.bootstrap(document.body, ['fbAngularApp']);
});
};
// Load the SDK Asynchronously
(function (d) {
var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
if (d.getElementById(id)) {
return;
}
js = d.createElement('script');
js.id = id;
js.async = true;
js.src = '//connect.facebook.net/' + window.fbConfig.lng + '/all.js';
ref.parentNode.insertBefore(js, ref);
}(document));
The only way that works is including the the sdk in your index page in the old way.
Because I have implemented the same solution from @blesh or extended version from @elviejo, both of them has a problem if we have a function which is called when the controller is invoked, the chance that FB
is not initialized is very high and this will make the call failed while calling a function from undefined
:)
Hope this will help others avoiding headache with this.