Question

I'm relatively new to Angular, so maybe what I ask is really simple. I want to load a Facebook comment box, my idea is to do this with a Angular directive.

This is my HTML code:

<div class="comments">
<div id="fb-root"></div>
<script>(function(d, s, id) {
    var js, fjs = d.getElementsByTagName(s)[0];
    if (d.getElementById(id)) return;
    js = d.createElement(s); js.id = id;
    js.src = "//connect.facebook.net/nl_NL/all.js#xfbml=1";
    fjs.parentNode.insertBefore(js, fjs);
    }(document, 'script', 'facebook-jssdk'));
</script>
<facebook-Comments href="{{track.share_url}}"></facebook-Comments>    
</div>

This is my directive:

angular.module( "CommentsDirectiveModule", [] )
.directive("facebookComments", function () {
  return {
      restrict: "E",
      scope: {
          code: "@href",
      },
      replace: true,
      template: '<fb:comments href="{{ur}}" width="300" numposts="5" colorscheme="light"></fb:comments>',
      link: function(scope) {
        scope.$watch("code", function (newVal) {
          if (newVal) {
            scope.url = $sce.trustAsResourceUrl(newVal);
          }
        });
      }
  };
} );

The {{track.share_url}} is passed to the directive and back to html. But the problem is that there is no Facebook comment box.

Does anyone no the reason for this problem?

Was it helpful?

Solution 2

I don't know how to write a working parse function in angularJS for my directive but this script did the trick for me:

https://github.com/pc035860/angular-easyfb

I followed the explanation, used this example: http://plnkr.co/edit/gFM1LV?p=preview and added this line to my HTML:

<div class="fb-comments" data-href="{{track.share_url}}" data-width="300px" data-numposts="5" data-colorscheme="light"></div>

OTHER TIPS

I had the same problem. Starting from your version:

  • I replaced the template attribute of the directive with a parse, keeping the original code but invoking re-evaluation
  • I replaced the effective href (that contains your initial angular {{url}} binding) with the document.location, because after reapplying angular didn't replace the url for me

The result that works for me:

Index.html

Here the Facebook SDK is loaded. Also the controllers and directive scripts are loaded.

<html class="" lang="en" id="ng-app" ng-app="myApp">
<head>
    <base href="/">
    <meta property="fb:admins" content="{6389564545}"/>
    <meta property="fb:app_id" content="{643503385720234}"/>
</head>
<body> 
    <div id="fb-root"></div>
    <script>(function(d, s, id) {
        var js, fjs = d.getElementsByTagName(s)[0];
        if (d.getElementById(id)) return;
        js = d.createElement(s); js.id = id;
        js.src = "//connect.facebook.net/nl_NL/all.js#xfbml=1&appId=643503385720456";
        fjs.parentNode.insertBefore(js, fjs);
        }(document, 'script', 'facebook-jssdk'));
    </script>

    <section class="section content">
       <div ng-view></div>
    </section> 

    <script src="/scripts/angular.min.js"></script>
    <script src="/scripts/angular-route.min.js"></script> 
    <script src="/angular/app.js"></script>
    <script src="/angular/controllers.js"></script>
    <script src="/angular/directives.js"></script>      

</body>
 </html>  

app.js

this loads the controllers and the directives, nothing really special going on here, just for reference.

angular.module('myApp', [
   'ngRoute',
   'myApp.controllers',
   'myApp.directives'
]) 
.config(['$routeProvider','$locationProvider', function($routeProvider, $locationProvider) { 
  $routeProvider.when('/home', {templateUrl: 'partials/home.html', controller: 'HomeController'});
  $routeProvider.when('/myEntity/:id', {templateUrl: 'partials/myEntity.html', controller: 'MyEntityController'});  
  $routeProvider.when('/contact', {templateUrl: 'partials/contact.html', controller: 'ContactController'});  
  $routeProvider.otherwise({redirectTo: '/home'});
  $locationProvider.html5Mode(true); 
}]); 

The magic in the directives.js

The directive binds on fb-comments (camel case is the default), C is indicating fb-comments is the class of the element it applies to. The element[0] is the div, the dataset is the set of html5 data attributes and the href is the data-href attribute. I set it to the current document.location.href (plain JavaScript). Then the FB.XFBML (that was loaded in the index.html) is used to parse the element again. Every time the DOM is changed and this element is involved, the directive kicks in and reapplies the Facebook comment code, resulting in the comment box.

angular.module('myApp.directives', [])
.directive('fbComments', function() {
    return {
        restrict: 'C',
        link: function(scope, element, attributes) { 
            element[0].dataset.href = document.location.href;
            return typeof FB !== "undefined" && FB !== null ? FB.XFBML.parse(element.parent()[0]) : void 0;
        }
    };
});

One line in the partial view myEntity.html

The element that the directive uses. This getLocation refers to the myEntityController in the controller.

<div class="fb-comments" data-href="{{getLocation()}}" data-numposts="10" data-colorscheme="light" data-width="580" id="commentbox"></div>

controllers.js

Has the getLocation method in scope, nothing else here.

angular.module('myApp.controllers', [])
  .controller('MyEntityController', ['$scope', '$routeParams', '$location',
function($scope, $routeParams, $location) {  

     $scope.id = $routeParams.id;   

     $scope.getLocation = function(){
      return document.location.href; 
 }       

}        
  ]);      

Good enough for me, I hope it will help other people too. Your first try should probably be using angular-easyfb

I think you're having issues because of the uppercase C in comments

your code:

<facebook-Comments href="{{track.share_url}}"></facebook-Comments>

should be:

<facebook-comments href="{{track.share_url}}"></facebook-comments>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top