August 01 2014

AngularJS directives for social sharing buttons - Facebook Like, Google+, Twitter and Pinterest

A few simple AngularJS directives that wrap the social sharing buttons: Facebook Like, Google Plus, Twitter Tweet and Pinterest Pin It.

Here they are in action: (See on Plunker at http://plnkr.co/edit/TQoIJ2?p=preview)

UPDATED 29/04/2015 - Enabled custom URL for Google+, Twitter and Pinterest buttons.

UPDATED 17/09/2014 - Refactored directives to automatically embed SDK for each social platform if not already loaded.

The buttons automatically update to the current URL as you navigate through your AngularJS app.

I'm setting the element html in the link function rather than using a template so the directive waits for all the data and APIs to be loaded before displaying anything.


Installation

  • Install using Bower: bower install angulike
  • Or download the code from GitHub and include the angulike.js file in your page, it's available on GitHub at https://github.com/cornflourblue/angulike
  • Or copy the AngularJS Directive sections below and add to your application

Add the 'angulike' module as a dependency of your AngularJS application:

angular.module('myApp', ['angulike']);

 

Usage


AngularJS Facebook Like

Create an empty div with the fb-like attribute:

<div fb-like></div>

To use a custom URL for the facebook like button:

<div fb-like="myModel.Url"></div>

 

AngularJS Google+ Share

Create an empty div with the google-plus attribute:

<div google-plus></div>

To use a custom URL for the google plus button:

<div google-plus="myModel.Url"></div>

 

AngularJS Twitter Tweet

Create an empty div with the tweet attribute, the value of the attribute contains the name of the model object for the tweet text:

<div tweet="myModel.Name"></div>

To use a custom URL for the tweet button:

<div tweet="myModel.Name" tweet-url="myModel.Url"></div>

 

AngularJS Pinterest PinIt

Create an empty div with the pin-it and pin-it-image attributes, the pin-it attribute contains the name of the model object for the description and the pin-it-image attribute contains the name of the model object for the image url:

<div pin-it="myModel.Name" pin-it-image="myModel.ImageUrl"></div>

To use a custom URL for the pinterest button:

<div pin-it="myModel.Name" pin-it-image="myModel.ImageUrl" pin-it-url="myModel.Url"></div>

 

AngularJS Controller to set the $scope variables used by the social share directives

Set the scope variables used by the directives in your controller:

angular.module('myApp')
  .controller('myController', [
      '$scope', function ($scope) {
          $scope.myModel = {
              Url: 'http://jasonwatmore.com/post/2014/08/01/AngularJS-directives-for-social-sharing-buttons-Facebook-Like-GooglePlus-Twitter-and-Pinterest.aspx',
              Name: "AngularJS directives for social sharing buttons - Facebook, Google+, Twitter and Pinterest | Jason Watmore's Blog", 
              ImageUrl: 'http://www.jasonwatmore.com/pics/jason.jpg'
          };
      }
  ]);

 

Set your Facebook App Id in your AngularJS App Run Method

angular.module('myApp', ['angulike'])
  .run([
      '$rootScope', function ($rootScope) {
          $rootScope.facebookAppId = '[FacebookAppId]'; // set your facebook app id here
      }
  ]);

 

 

Breakdown of the AngularJS Social Sharing Buttons Code

Below is a breakdown of how the angular social sharing buttons are implemented, for those interested in the nuts and bolts.

 

AngularJS Facebook Like Button Directive

angular.module('angulike')
    .directive('fbLike', [
        '$window', '$rootScope', function ($window, $rootScope) {
            return {
                restrict: 'A',
                scope: {
                    fbLike: '=?'
                },
                link: function (scope, element, attrs) {
                    if (!$window.FB) {
                        // Load Facebook SDK if not already loaded
                        $.getScript('//connect.facebook.net/en_US/sdk.js', function () {
                            $window.FB.init({
                                appId: $rootScope.facebookAppId,
                                xfbml: true,
                                version: 'v2.0'
                            });
                            renderLikeButton();
                        });
                    } else {
                        renderLikeButton();
                    }

                    var watchAdded = false;
                    function renderLikeButton() {
                        if (!!attrs.fbLike && !scope.fbLike && !watchAdded) {
                            // wait for data if it hasn't loaded yet
                            watchAdded = true;
                            var unbindWatch = scope.$watch('fbLike', function (newValue, oldValue) {
                                if (newValue) {
                                    renderLikeButton();
									  
                                    // only need to run once
                                    unbindWatch();
                                }
                                  
                            });
                            return;
                        } else {
                            element.html('<div class="fb-like"' + (!!scope.fbLike ? ' data-href="' + scope.fbLike + '"' : '') + ' data-layout="button_count" data-action="like" data-show-faces="true" data-share="true"></div>');
                            $window.FB.XFBML.parse(element.parent()[0]);
                        }
                    }
                }
            };
        }
    ]);

 

AngularJS Google Plus Button Directive

angular.module('angulike')
    .directive('googlePlus', [
        '$window', function ($window) {
            return {
                restrict: 'A',
                scope: {
                    googlePlus: '=?'
                },
                link: function (scope, element, attrs) {
                    if (!$window.gapi) {
                        // Load Google SDK if not already loaded
                        $.getScript('//apis.google.com/js/platform.js', function () {
                            renderPlusButton();
                        });
                    } else {
                        renderPlusButton();
                    }

                    var watchAdded = false;
                    function renderPlusButton() {
                        if (!!attrs.googlePlus && !scope.googlePlus && !watchAdded) {
                            // wait for data if it hasn't loaded yet
                            watchAdded = true;
                            var unbindWatch = scope.$watch('googlePlus', function (newValue, oldValue) {
                                if (newValue) {
                                    renderPlusButton();

                                    // only need to run once
                                    unbindWatch();
                                }

                            });
                            return;
                        } else {
                            element.html('<div class="g-plusone"' + (!!scope.googlePlus ? ' data-href="' + scope.googlePlus + '"' : '') + ' data-size="medium"></div>');
                            $window.gapi.plusone.go(element.parent()[0]);
                        }
                    }
                }
            };
        }
    ]);

 

AngularJS Twitter Tweet Button Directive

angular.module('angulike')
    .directive('tweet', [
        '$window', '$location',
        function ($window, $location) {
            return {
                restrict: 'A',
                scope: {
                    tweet: '=',
                    tweetUrl: '='
                },
                link: function (scope, element, attrs) {
                    if (!$window.twttr) {
                        // Load Twitter SDK if not already loaded
                        $.getScript('//platform.twitter.com/widgets.js', function () {
                            renderTweetButton();
                        });
                    } else {
                        renderTweetButton();
                    }

					var watchAdded = false;
                    function renderTweetButton() {
                        if (!scope.tweet && !watchAdded) {
                            // wait for data if it hasn't loaded yet
							watchAdded = true;
                            var unbindWatch = scope.$watch('tweet', function (newValue, oldValue) {
							    if (newValue) {
                                    renderTweetButton();
								  
								    // only need to run once
								    unbindWatch();
								}
                            });
                            return;
                        } else {
                            element.html('<a href="https://twitter.com/share" class="twitter-share-button" data-text="' + scope.tweet + '" data-url="' + (scope.tweetUrl || $location.absUrl()) + '">Tweet</a>');
                            $window.twttr.widgets.load(element.parent()[0]);
                        }
                    }
                }
            };
        }
    ]);

 

AngularJS Pinterest PinIt Button Directive

angular.module('angulike')
    .directive('pinIt', [
        '$window', '$location',
        function ($window, $location) {
            return {
                restrict: 'A',
                scope: {
                    pinIt: '=',
                    pinItImage: '=',
                    pinItUrl: '='
                },
                link: function (scope, element, attrs) {
                    if (!$window.parsePins) {
                        // Load Pinterest SDK if not already loaded
                        (function (d) {
                            var f = d.getElementsByTagName('SCRIPT')[0], p = d.createElement('SCRIPT');
                            p.type = 'text/javascript';
                            p.async = true;
                            p.src = '//assets.pinterest.com/js/pinit.js';
                            p['data-pin-build'] = 'parsePins';
                            p.onload = function () {
                                if (!!$window.parsePins) {
                                    renderPinItButton();
                                } else {
                                    setTimeout(p.onload, 100);
                                }
                            };
                            f.parentNode.insertBefore(p, f);
                        }($window.document));
                    } else {
                        renderPinItButton();
                    }

					var watchAdded = false;
                    function renderPinItButton() {
                        if (!scope.pinIt && !watchAdded) {
                            // wait for data if it hasn't loaded yet
							watchAdded = true;
                            var unbindWatch = scope.$watch('pinIt', function (newValue, oldValue) {
							    if (newValue) {
								    renderPinItButton();
									  
									// only need to run once
									unbindWatch();
								}
                            });
                            return;
                        } else {
                            element.html('<a href="//www.pinterest.com/pin/create/button/?url=' + (scope.pinItUrl || $location.absUrl()) + '&media=' + scope.pinItImage + '&description=' + scope.pinIt + '" data-pin-do="buttonPin" data-pin-config="beside"></a>');
                            $window.parsePins(element.parent()[0]);
                        }
                    }
                }
            };
        }
    ]);

 

Web Development and AngularJS Consultant Sydney

Feel free to drop me a line if you're looking for web development or AngularJS development or consulting services in Sydney Australia, I also provide remote contracting services for clients outside Sydney.


Sponsored by