Search code examples
jquerywebsocketangularjsdynamic-datajquery-isotope

Making AngularJS + JQuery Isotope + Dynamic content play well together


In my page AngularJS' html templates are bound to the controller's variables as usual. I'm using WebSockets & when I receive a new item I update the scope's values and call angular's $apply. This works fine, AngularJS correctly updates the view rendering any new items added/removed...

The tricky part is bringing the Isotope plugin into the mix. Since the content is dynamic adding items to Isotope ( http://isotope.metafizzy.co/docs/adding-items.html ) isn't straightforward for a few reasons:

  • On updating the controller's data and calling apply angular creates the additional elements required.
  • Isotope requires you to know each item you want to add.
  • I don't think there is a way for AngularJS to tell the controller what html item was created.

Has anyone gotten these 3 pieces of to work together? Is there a way of getting the HTML created so it can be passed to Isotope?


Solution

  • I'll assume you are using ng-repeat to generate the view/HTML.

    Here's something you can try: create a directive and attach it to the same element where the ng-repeat(s) is/are. Set the directive's priority such that it runs last (or after other directives). Have the directive's link function watch the same $scope properties that you updated as a result of the web sockets information (or I suppose you could just create some kind of counter on the scope that you increment each time something changes -- watch that counter in the directive). When the directive/watch detects a change, extract the new HTML (via the link function's element attribute) and send it to isotope.

    You'll probably need to set some scope properties in the controller that the watch callback can access to determine which items were added/removed.

    link: function(scope, element, attrs, someController) {
        scope.$watch(..., function(newValue) {
           // extract HTML with Angular or jQuery
           var children = element.children();
           for(i=scope.first_new_item; i<= scope.last_new_item; i++) {
               $('#isotope_container').isotope('insert'), children[i]);
           }
           // handle removed items similarly ??
        }
    

    contents() might work better than children(), or use jQuery selectors.