Thursday, February 23, 2012 12:35 PM Jim Wang

Implementing a Facebook Like Button with Knockout.js

Recently I’ve been playing around with Knockout.js, and one of the features I wanted to implement was a Facebook like button inside of the details view of a master-detail. Facebook provides the following code snippet for their JavaScript SDK:

<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/en_US/all.js#xfbml=1&appId=10349446178";
        fjs.parentNode.insertBefore(js, fjs);
    } (document, 'script', 'facebook-jssdk'));
</script>

As well as the following markup snippet for the actual like button implementation.

<div class="fb-like" 
  data-send="true"
  data-show-faces="false" 
  data-href="www.facebook.com">
</div>

Unfortunately, if you simply try the following code – things will not work as you change the details view as the Facebook SDK will not reparse the page to update the URL and render the Like button.

<div class="fb-like" 
  data-send="true" 
  data-show-faces="false" 
  data-bind="'data-href': myUrl">
</div>

Fortunately there’s a simple workaround – create your own binding handler, and then call Facebook’s JS API directly to reparse the markup that you have for the like button. Here’s the binding handler:

ko.bindingHandlers.likeButton = {
  update: function (element, valueAccessor) {
    $(element).attr('data-href', valueAccessor());
    FB.XFBML.parse();
  }
}

Note that I can also be more specific by calling FB.XFBML.parse() on the specific element that contains the like button (not the actual like button itself, for reasons I did not investigate further – likely this is an implementation detail on Facebook’s side). Intuitively though, you should probably pick the containing div as a target for the parse() call for the best performance.

Then simply update your markup to this:

<div class="fb-like"
  data-send="true"
  data-show-faces="false"
  data-bind="likeButton: myUrl">
</div>

And you’re done!

Filed under: , ,

Comments

No Comments