Angular and isotopic - Addition of a new element in the isotopic context

advertisements

UPDATE: After some very insightful code from @Marc Kline, I went back and cleaned up my page. It turned out that I had my controllers listed in reversed (My angular controller was inside the Isotope controller, instead of the other way round). Once I changed it back and cleaned off some additional scripting, it started working again. I have updated the code snippet to reflect the change. Thanks to Marc and S.O!

I am having trouble figuring out how can I add new items using Angular and still let Isotope manage their UI display.

I am using Isotope and Angular to render server results in a masonry style layout. When I add new items to the layout on a button click, angular adds it just fine. However, they do not appear in the context of the isotope UI and appear separately (and cannot be sorted, laid out or filtered using Isotope).

Here is my JS Code

    <!-- Define controller -->
    var contrl = app.controller("MainController", function($scope){
        $scope.items ={!lstXYZ}; //JSON data from server

//Function called by button click
        $scope.addItem = function(item)
        {
          $scope.items.push(item);
          $scope.item = {};
        }
    });

    contrl.$inject = ['$scope'];

Here is the HTML to display the server results...(Updated to show working code..refer comments)

<div ng-controller="MainController">
 <div class="isotope" id="isotopeContainer">
      <div ng-repeat="item in items">
        <div class='element-item {{item.status}}' data-category='{{item.status}}'>
          <p class="number">{{item.type}}</p>
        </div>
      </div>
    </div>
  </div>

And here is my HTML button to add the new items

  <table>
    <tr>
      <td><input type="text" ng-model="item.status" /></td>
    </tr>
    <tr>
      <td><input type="text" ng-model="item.type" /></td>
    </tr>
    <tr>
      <td colspan="2"><input type="Button" value="Add" ng-click="addItem(item)" /> </td>
    </tr>
  </table>

I am not sure how do I ensure that Isotope can recognize the newly added element and re-animate the layout.

Any help or pointers will be very appreciated. Thanks!


ng-repeat takes care of adding the new element to the DOM for you. However, Isotope isn't doing any "watching" for you - you have to manually invoke a redraw of the container.

You could just add something like $("#isotopeContainer").isotope(...) directly to your controller, but in the spirit of keeping your controllers lean and free of DOM-related code, you should instead create a service. Something like:

myApp.service('Isotope', function(){

  this.init = function(container) {
    $(container).isotope({itemSelector: '.element-item'});
  };

  this.append = function(container, elem) {
    $(container).isotope('appended', elem);
  }

});

... where the first method initializes a new Isotope container and the next redraws the container after an item is appended.

You could then inject this service into any controller or directive, but directives probably are best for this scenario. In this Plunker, I created two new directives: one for Isotope containers and another for Isotype elements, and used the service to do the initialization and redrawing.