Integrating Gigya Comments with Angular App

566 views
Skip to first unread message

Rodney Gracia

unread,
Sep 15, 2014, 2:39:15 PM9/15/14
to ang...@googlegroups.com

So I have a project that requires me to have a third party integration with a commenting service (Gigya). In the controller I am using a factory that gets the JSON feed for the articles. 

I have the 3rd party JavaScript code that is supposed to update every time a new article from the feed is being viewed. I am using Views and Routing in order to reuse the index.html and load a partial for article details. That partial should contain the following code that will show comments from our public web site:

<div id="commentsDiv"></div>
<script type="text/javascript">
    var params =
    {
        categoryID: 7623701,
        streamID: '',
        version: 2,
        containerID: 'commentsDiv',
        cid:'',
        enabledShareProviders: 'facebook,twitter,linkedin'
    }
    gigya.comments.showCommentsUI(params);
</script>


The controller associated with that partial for article details uses $routeParams.itemId; to determine what article is being used and create the data object to supply values for all properties being displayed. The 3rd party script above needs one of the properties in the data (PostID) as the streamID value in order for comments to be tracked and synchronized. So obviously I cannot do this:

<div id="commentsDiv"></div>
<script type="text/javascript">
    var params =
    {
        categoryID: 7623701,
        streamID: '{{stories[whichItem].PostID}}',
        version: 2,
        containerID: 'commentsDiv',
        cid:'',
        enabledShareProviders: 'facebook,twitter,linkedin'
    }
    gigya.comments.showCommentsUI(params);
</script>

As {{stories[whichItem].PostID}} cannot be compiled inside the script. How would I go about making that value for PostID in the current Article to become a value I can pass into this 3rd party script?

Rodney Gracia

unread,
Sep 15, 2014, 2:45:46 PM9/15/14
to ang...@googlegroups.com

Forgot to mention something important. The AngularJS App in question is using a feed from our web site to populate a SPA in an iOS App using a Web View. So the feed gets refreshed every 15 mins to contain the latest 50 articles in several categories. So using $routeParams.itemId is not possible as that value is reassigned inside the AngularJS App every time the feed is refreshed. So we have to use the unique PostID in the feed instead so we can always attach to the correct article from the web site and retrieve its comments to be displayed in the AngularJS App and allow for adding comments too within it that will also be pushed to the web site as part of the Gigya sync services.

dinesh kumar

unread,
Sep 16, 2014, 12:49:23 AM9/16/14
to ang...@googlegroups.com
Hi Rodney,

Is the commentsdiv is part of the partial views
Or will it remains same as the page navigates ?

Regards
Dinesh kumar l

Rodney Gracia

unread,
Sep 16, 2014, 10:20:34 AM9/16/14
to ang...@googlegroups.com
Hi Dinesh,

The commentsDiv is part of Gigya mandatory code and yes it is in the partial. So here are all the files affecting this functionality (code abbreviated for company privacy policies):

The App Routing (app.js):

(function() {
  var myApp = angular.module('myApp', [
    'ngRoute',
    'ngSanitize',
    'angular-carousel'
  ]);
    
    myApp.config(['$routeProvider', function($routeProvider) {
    $routeProvider.
    when('/exclusives', {
      templateUrl: 'partials/articles.html',
      controller: 'ExclusivesController'
    }).
    when('/videos', {
      templateUrl: 'partials/videos.html',
      controller: 'VideosController'
    }).
    when('/galleries', {
      templateUrl: 'partials/galleries.html',
      controller: 'GalleriesController'
    }).
    when('/thankyou', {
      templateUrl: 'partials/thank-you.html'
    }).
    when('/details/:itemId', {
      templateUrl: 'partials/article-datail.html',
      controller: 'DetailsController'
    }). 
    when('/video/:itemId', {
      templateUrl: 'partials/video-datail.html',
      controller: 'VideoController'
    }).   
    when('/gallery/:itemId', {
      templateUrl: 'partials/gallery-datail.html',
      controller: 'GalleryController'
    }). 
    otherwise({
      redirectTo: '/exclusives'
    });
    
  }]);
}());

Article Channel List Controller (exclusivesController.js):

(function() {
    
    var ExclusivesController = function($scope, $http, $sce, dataFactory) {
        $scope.stories = [];
        $scope.totalDisplayed = 25;
        $scope.loadMore = function () {
          $scope.totalDisplayed += 25;
        };
        function init() {
            dataFactory.getStories()
            .success(function(stories) {
              $scope.stories = stories.articles;
           
           $scope.SkipValidation = function(value) {
           return $sce.trustAsHtml(value);
          };
            })
            .error(function(data, status, headers, config) {
                $log.log(data.error + ' ' + status);
            });
            
            $scope.numberOfRecords = function() {
                return $scope.stories.length;                
            };
        }
        
        init();
    };
    
    ExclusivesController.$inject = ['$scope', '$http', '$sce', 'dataFactory'];

    angular.module('myApp')
      .controller('ExclusivesController', ExclusivesController);
    
}());

Data Factory for Channel and Article details (dataFactory.js):

(function() {
    var dataFactory = function($http) {
    
        var factory = {};
        
        factory.getStories = function() {
            return $http.get('../../articles.json');
        };
        
        return factory;
    };
    
    dataFactory.$inject = ['$http'];
        
    angular.module('myApp').factory('dataFactory', 
                                    dataFactory);
                                           
}());

Article Details Controller (detailsController.js):

(function() {

  var DetailsController = function($scope, $http, $routeParams, $sce, dataFactory) {
  storyId = $routeParams.itemId;
  uniqueId = "Art" + $routeParams.itemId;
  nextItem = $routeParams.itemId++;
  $scope.stories = [];
  
    function init() {
      dataFactory.getStories().success(function(stories) {
        $scope.stories = stories.articles;
        $scope.whichItem = storyId; 
        $scope.nextArticle  = nextItem;
        $scope.totalList = stories.articles.length;
     $scope.SkipValidation = function(value) {
     return $sce.trustAsHtml(value);
    };    
      })
      .error(function(data, status, headers, config) {
          $log.log(data.error + ' ' + status);
      });
      
      $scope.todaysDate = new Date();   
      
      var params = {
      categoryID: 'Articles',
      streamID: uniqueId,
      version: 2,
      containerID: 'commentsDiv',
      cid:''
      }
      gigya.comments.showCommentsUI(params);
    }
     init();
    
  };
 
  DetailsController.$inject = ['$scope', '$http', '$routeParams', '$sce', 'dataFactory'];

  angular.module('myApp')
    .controller('DetailsController', DetailsController);

}());

Article Details Partial (article-datail.html):

<section ng-model="articles" class="story-details">
<div class="article-nav"><a class="prev-article" href="#/details/{{stories.indexOf(stories[nextArticle-1])}}" ng-disabled="whichItem == 0">Previous Story</a> <a href="#/details/{{stories.indexOf(stories[nextArticle+1])}}" class="next-article"  ng-disabled="stories[nextArticle+1] == undefined">Next Story</a></div>
<article>
 <h2>{{stories[whichItem].title}}</h2>
 <div class="date">Posted on {{stories[whichItem].pubDate  | date:"MMMM d',' yyyy '@' h:mm a" }}</div>
 <div class="sharing-widget">
   <a class="twitter_custom" href="https://twitter.com/home?status=Via: @radar_online: {{stories[whichItem].title}}: {{stories[whichItem].link}}"></a>
   <a class="plusone_custom" href="https://plus.google.com/share?url={{stories[whichItem].link}}"></a>
   <!-- <a class="tumblr_custom" href="http://www.tumblr.com/share/link?url={{stories[whichItem].link}}"></a> -->
   <a class="email_custom" href="mailto:?&subject=I wanted you to see this article.&body=Check out this article: {{stories[whichItem].title}} {{stories[whichItem].link}}." title="Share by Email"></a>
 </div>
 <img  height="169" width="300" class="lead" ng-src="{{stories[whichItem].featuredImage}}">
   <span ng-bind-html="SkipValidation(stories[whichItem].description)"></span>
 <div class="author"><img ng-src="{{stories[whichItem].authorPhoto}}"> <span>By {{stories[whichItem].byline}}</span></div>
</article>
<div class="article-nav"><a class="prev-article" href="#/details/{{stories.indexOf(stories[nextArticle-1])}}" ng-disabled="whichItem == 0">Previous Story</a> <a href="#/details/{{stories.indexOf(stories[nextArticle+1])}}" class="next-article"  ng-disabled="stories[nextArticle+1] == undefined">Next Story</a></div>
<div id='commentsDiv'></div>
</section>


Finally The Index.html:

<!DOCTYPE html>
<html class="no-js" lang="en" ng-app="myApp">
  <head>
    <meta charset="utf-8">
    <base href="/">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1 user-scalable=no">
    <title>Mobile</title>
    
    <!-- Site Styles -->
    <link rel="stylesheet" href="css/style.css">  
    <link rel="stylesheet" href="lib/angular-carousel/angular-carousel.min.css">
    
    <!-- jQuery and site js -->
    <script src='http://cdn.gigya.com/JS/gigya.js type='text/javascript'></script>
    <script src="lib/jpanelmenu.min.js"></script>
    <script src="js/scripts.min.js"></script>
    
    <!-- Angular Scripts -->
    <script src="lib/angular.min.js"></script>
    <script src="lib/angular-route.min.js"></script>
    <script src="lib/angular-sanitize.min.js"></script>
    <script src="lib/angular-touch.min.js"></script>
    <script src="lib/angular-carousel/angular-carousel.min.js"></script> 

  </head>
  <body unresolved ng-cloak touch-action="auto">   
    <div id="main-container"> 
      
      <div id="site-content" class="stories-summary" ng-view></div>
      <footer ng-controller="DateController" id="footer">© {{myDate | date:"yyyy"}}</footer>
    </div><!--  End of main container -->
    
    <!-- Mobile Menu -->
    <ul id="mobile-menu" class="mobile-menu">
      <li ng-controller="DateController" class="menu-date">{{myDate | date:"MMMM d',' yyyy"}}</li>
      <li><a href="/#/exclusives" target="_self">Breaking News</a></li>
      <li><a href="/#/videos" target="_self">Videos</a></li>
      <li><a href="/#/galleries" target="_self">Galleries</a></li>
      <li><a href="juice.html" target="_self">The Daily Juice</a></li>
    </ul>
    
    <!-- Compiled app files -->  
    <script src="js/app.min.js"></script>
    <script src="js/services/dataFactory.min.js"></script>
    <script src="js/services/videosFactory.min.js"></script>
    <script src="js/services/galleriesFactory.min.js"></script>
    <script src="js/controllers/exclusivesController.min.js"></script>
    <script src="js/controllers/detailsController.min.js"></script>
    <script src="js/controllers/dateController.min.js"></script>
    <script src="js/controllers/tipsController.min.js"></script>
    <script src="js/controllers/videosController.min.js"></script>
    <script src="js/controllers/videoController.min.js"></script>
    <script src="js/controllers/galleryController.min.js"></script>
    <script src="js/controllers/galleriesController.min.js"></script>

  </body>
</html>





Rodney Gracia

unread,
Sep 16, 2014, 11:10:04 AM9/16/14
to ang...@googlegroups.com
I know I am not supposed to add that 3rd party javscript in the controller and that belongs in a directive instead. Tese files reflect our testing status. Ideally we would move the comments functionality to a directive once we find a way to hook it up to the PostID value.

dinesh kumar

unread,
Sep 17, 2014, 8:35:29 AM9/17/14
to ang...@googlegroups.com
hi rodney,

wrapping this code in a directive is the right way to do it.

if you need a sample work around i'll give you one.

Thanks
Dinesh kumar.L

Message has been deleted

Rodney Gracia

unread,
Sep 17, 2014, 9:42:00 AM9/17/14
to ang...@googlegroups.com
Hi Dinesh,

You think this is doable? if you do can you post what your workaround would be? I am completely stuck with this.

dinesh kumar

unread,
Sep 17, 2014, 10:14:15 AM9/17/14
to ang...@googlegroups.com
hi rodney,

check this link.

revert me if you have any problem

Regards
Dinesh kumar.L

Rodney Gracia

unread,
Sep 17, 2014, 11:41:26 AM9/17/14
to ang...@googlegroups.com
Thank you Dinesh.

Ok I have managed to move my code to a directive and it works as long as I use this:

$scope.streamid = $routeParams.itemId;


However, I cannot use $routeParams.itemId as the the streamID because that value will be reused next time our feed gets replaced. The value I was asked to use is in the JSON feed of articles stored as PostID. How do I retrieve that value at the controller stage? or is that not possible? That value is only available only after angular has compiled and rendered the view.

Michael Bielski

unread,
Sep 17, 2014, 11:51:25 AM9/17/14
to ang...@googlegroups.com
Please forgive me if I am suggesting something that you have already tried, but if you need to capture the value of $routeParams.itemId at any one moment you can use angular.copy();

$scope.streamid = angular.copy($routeParams.itemId);

This will set the value of your $scope variable to the value of $routeParams.itemId without creating a binding to it. Now the two values can change independently and not mess with the other one.

Rodney Gracia

unread,
Sep 17, 2014, 12:00:55 PM9/17/14
to ang...@googlegroups.com
Hi Michael,

I am not having any problems retrieving $routeParams.itemId. I can get that value fine, the problem is that the feed for the app gets replaced every 15 minutes and that value gets assigned to another article all together. So in order to sync data for the previews article that had that value is impossible. So $routeParams.itemId is not a good value for streamID. it needs to be set to a value that is in the feed as an element called PostID. So I tried this:

$scope.stories[$scope.whichItem].PostID

But it is showing undefined at the time it called in the controller. There has to be a way to tell angular that the value for $scope.stories[$scope.whichItem].PostID will exist when the view loads.

Rodney Gracia

unread,
Sep 17, 2014, 1:19:10 PM9/17/14
to ang...@googlegroups.com
So here is where my code stands so far:

My details view controller:

(function() {

  var DetailsController = function($scope, $http, $routeParams, $sce, dataFactory) {
  storyId = $routeParams.itemId;
  nextItem = $routeParams.itemId++;
  $scope.stories = [];
  
    function init() {
      dataFactory.getStories().success(function(stories) {
        $scope.stories = stories.articles;
        $scope.whichItem = storyId;       
        //$scope.theID = $scope.stories[$scope.whichItem].PostID;
        $scope.nextArticle  = nextItem;
        $scope.totalList = stories.articles.length;
     $scope.SkipValidation = function(value) {
     return $sce.trustAsHtml(value);
    };    
      })
      .error(function(data, status, headers, config) {
          $log.log(data.error + ' ' + status);
      });
      
      $scope.todaysDate = new Date();  
      
      //assign the steam id
      $scope.streamid = $routeParams.itemId;
      
      $scope.params = {
        categoryID: 'Articles',
        streamID: $scope.streamid,
        version: 2,
        containerID: 'commentsDiv',
        cid:'',
        enabledShareProviders: ''
      }; 
    }
     init();
    
  };
 
  DetailsController.$inject = ['$scope', '$http', '$routeParams', '$sce', 'dataFactory'];

  angular.module('myApp')
    .controller('DetailsController', DetailsController);

}());

My Directive:

angular.module('myApp').directive('gigdirective', function () {
  return{
    template:"<div id='commentsDiv'></div>",
    scope:{
      "gigparams":"="
    },
    link:function(scope,ele,attr){
      /* uncomment the below code once you finish development */
      console.log(scope.gigparams);
     
      gigya.comments.showCommentsUI(scope.gigparams);
    }
  }

});

And my partial that handles the details:

<section ng-model="articles" class="story-details" id="main">
<div class="article-nav"><a class="prev-article" href="#/details/{{stories.indexOf(stories[nextArticle-1])}}" ng-disabled="whichItem == 0">Previous Story</a> <a href="#/details/{{stories.indexOf(stories[nextArticle+1])}}" class="next-article"  ng-disabled="stories[nextArticle+1] == undefined">Next Story</a></div>


<article id="main-article" data-post-id="{{stories[whichItem].PostID}}">
 <h2>{{stories[whichItem].title}}</h2>
 <div class="date">Posted on {{stories[whichItem].pubDate  | date:"MMMM d',' yyyy '@' h:mm a" }}</div>
 <div class="sharing-widget">
   <a class="twitter_custom" href="https://twitter.com/home?status=Via: @radar_online: {{stories[whichItem].title}}: {{stories[whichItem].link}}"></a>
   <a class="plusone_custom" href="https://plus.google.com/share?url={{stories[whichItem].link}}"></a>
   <!-- <a class="tumblr_custom" href="http://www.tumblr.com/share/link?url={{stories[whichItem].link}}"></a> -->
   <a class="email_custom" href="mailto:?&subject=I wanted you to see this article.&body=Check out this article: {{stories[whichItem].title}} {{stories[whichItem].link}}." title="Share by Email"></a>
 </div>
 <img  height="169" width="300" class="lead" ng-src="{{stories[whichItem].featuredImage}}">
   <span ng-bind-html="SkipValidation(stories[whichItem].description)"></span>
 <div class="author"><img ng-src="{{stories[whichItem].authorPhoto}}"> <span>By {{stories[whichItem].byline}}</span></div>
</article>
{{stories[whichItem].PostID}}
<div class="article-nav"><a class="prev-article" href="#/details/{{stories.indexOf(stories[nextArticle-1])}}" ng-disabled="whichItem == 0">Previous Story</a> <a href="#/details/{{stories.indexOf(stories[nextArticle+1])}}" class="next-article"  ng-disabled="stories[nextArticle+1] == undefined">Next Story</a></div>
<div gigdirective gigparams="params" ></div>
</section>


As this code stands this works by setting 
$scope.streamid = $routeParams.itemId;

However, itemID is reused on this app because the feed gets replaced with the latest 50 articles of our public site. The feed, however has a PostID for each article that will always be a unique number that we can use aas streamID forever. it will never change for the said article. 

The problem is that PostID is undefined at the Controller stage and at the Directive stage. That value only exists after Angular compiles and makes it available to my partial. 

The question is, can that value be accessed or made available as a placeholder of sorts until the view is rendered and somehow make this work?

dinesh kumar

unread,
Sep 18, 2014, 3:40:23 AM9/18/14
to ang...@googlegroups.com
hi rodney,

probably u can save the PostId in $rootscope.

regards
Dinesh kumar.L


Rodney Gracia

unread,
Sep 18, 2014, 9:36:25 AM9/18/14
to ang...@googlegroups.com
We found a solution. I will be testing it thoroughly today and tomorrow and pasting the final code here for anyone following this thread.

Rodney Gracia

unread,
Sep 19, 2014, 3:04:24 PM9/19/14
to ang...@googlegroups.com
So here is the final solution. Thanks all for your feedback. We could not have fixed it without this group.

Details Controller:

(function() {

  var DetailsController = function($scope, $http, $routeParams, $sce, dataFactory) {
  storyId = $routeParams.itemId;
  nextItem = $routeParams.itemId++;
  $scope.stories = [];

    function init() {
      dataFactory.getStories().success(function(stories) {
        $scope.stories = stories.articles;
        $scope.whichItem = storyId;
        $scope.$emit('gigya', $scope.stories[storyId].PostID);
        $scope.nextArticle  = nextItem;
        $scope.totalList = stories.articles.length;
        
     $scope.SkipValidation = function(value) {
     return $sce.trustAsHtml(value);
    };    
      })
      .error(function(data, status, headers, config) {
          $log.log(data.error + ' ' + status);
      });
      
      $scope.todaysDate = new Date();  
    }
     init();
    
  };
 
  DetailsController.$inject = ['$scope', '$http', '$routeParams', '$sce', 'dataFactory'];

  angular.module('myApp')
    .controller('DetailsController', DetailsController);

}());

Directive:

angular.module('myApp').directive('gigyaComments', function () {
  return{
    template:"<div id='commentsDiv'></div>",
    link:function(scope,elem,attrs){
        scope.$on('gigya', function(event, data) {
            var params = {
                categoryID: 'Articles',
                streamID: data,
                version: 2,
                containerID: 'commentsDiv',
                cid:'',
                enabledShareProviders: '',
                useHiResIcons: true,
                showLoginBar: true,
                enabledProviders: "facebook,twitter,google"
            };
            gigya.comments.showCommentsUI(params);
        });
    }
  }

});

Partial for details page:

<section ng-model="articles" class="story-details" id="main">
<div class="article-nav"><a class="prev-article" href="#/details/{{stories.indexOf(stories[nextArticle-1])}}" ng-disabled="whichItem == 0">Previous Story</a> <a href="#/details/{{stories.indexOf(stories[nextArticle+1])}}" class="next-article"  ng-disabled="stories[nextArticle+1] == undefined">Next Story</a></div>


<article id="main-article" data-post-id="{{stories[whichItem].PostID}}">
 <h2>{{stories[whichItem].title}}</h2>
 <div class="date">Posted on {{stories[whichItem].pubDate  | date:"MMMM d',' yyyy '@' h:mm a" }}</div>
 <div class="sharing-widget">
   <a class="twitter_custom" href="https://twitter.com/home?status=Via: @radar_online: {{stories[whichItem].title}}: {{stories[whichItem].link}}"></a>
   <a class="plusone_custom" href="https://plus.google.com/share?url={{stories[whichItem].link}}"></a>
   <!-- <a class="tumblr_custom" href="http://www.tumblr.com/share/link?url={{stories[whichItem].link}}"></a> -->
   <a class="email_custom" href="mailto:?&subject=I wanted you to see this article.&body=Check out this article: {{stories[whichItem].title}} {{stories[whichItem].link}}." title="Share by Email"></a>
 </div>
 <img  height="169" width="300" class="lead" ng-src="{{stories[whichItem].featuredImage}}">
   <span ng-bind-html="SkipValidation(stories[whichItem].description)"></span>
 <div class="author"><img ng-src="{{stories[whichItem].authorPhoto}}"> <span>By {{stories[whichItem].byline}}</span></div>
</article>
<div class="article-nav"><a class="prev-article" href="#/details/{{stories.indexOf(stories[nextArticle-1])}}" ng-disabled="whichItem == 0">Previous Story</a> <a href="#/details/{{stories.indexOf(stories[nextArticle+1])}}" class="next-article"  ng-disabled="stories[nextArticle+1] == undefined">Next Story</a></div>
<div gigya-comments="{{stories[whichItem].PostID}}" ></div>
</section>


dinesh kumar

unread,
Sep 19, 2014, 8:50:59 PM9/19/14
to ang...@googlegroups.com
Hi Rodney,

I'm happy you have fixed the issue.

If u find time to improve this code,use $scope.$watch in this instance,it fits perfect here,because watch is made to trigger an event if there is any change in particular or any variable in scope

Regards
Dinesh kumar l

Gajanan Ghuge

unread,
Mar 24, 2015, 6:40:23 AM3/24/15
to ang...@googlegroups.com
hi,
 i am going to integrate gigya in angularjs and nodejs application can you help how to integrate
please reply very soon thanks 
Reply all
Reply to author
Forward
0 new messages