Angularjs with Packery.js

All we need is an easy explanation of the problem, so here it is.

Trying to get Packery.js working with an angularjs app I’m working with.

For some reason they don’t seem to play nice together. I thought it might be resolved with the isInitLayout false setting however, still no love.

Here is my (bootstrap 3) HTML:

<div class="row" class="js-packery" 
     data-packery-options='{ "itemSelector": ".packery-item", 
                             "gutter": 10,  
                             "columnWidth": 60, 
                             "isInitLayout": false }'>
    <artifact class="packery-item" ng-repeat="(index, thing) in data | limitObjectTo:4" thing="thing"></artifact>
</div>

I’m starting to wonder if it’s because of the Artifact directive i’m using…

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

As mentioned earlier, you have to make a directive that handles the use of Packery.

This directive made Packery work with AngularJS in the project I am working on.

Working fiddle: http://jsfiddle.net/8P6mf/2/

HTML:

<div class="wrapper">
    <div ng-repeat="item in test" danny-packery>
        {{item.name}}
    </div>
</div>

JavaScript:

var dannyPackery = app.directive('dannyPackery', ['$rootScope', function($rootScope) {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            console.log('Running dannyPackery linking function!');
            if($rootScope.packery === undefined || $rootScope.packery === null){
                console.log('making packery!');
                $rootScope.packery = new Packery(element[0].parentElement, {columnWidth: '.item'});
                $rootScope.packery.bindResize();
                $rootScope.packery.appended(element[0]);
                $rootScope.packery.items.splice(1,1); // hack to fix a bug where the first element was added twice in two different positions
            }
            else{
                $rootScope.packery.appended(element[0]);
            }
            $rootScope.packery.layout();
        }
    };
}]);

Method 2

Any JS library you find will not simply work with Angular. Angular does compilation of the DOM which causes other libraries to lose the context. You must write a custom directive.

I found an existing directive for Masonry: https://github.com/passy/angular-masonry and packery is pretty similar to Masonry so I’m sure you can adapt it for packery.

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply