I am developing an \"art gallery\" app.
Feel free to pull down the source on github and play around with it.
Plunker with full
I've been playing around with this a bit more and @ganaraj's answer is pretty neat. If you stick a $element.masonry('resize'); in his controller's appendBrick method and account for
the images loading then it looks like it works.
Here's a plunker fork with it in: http://plnkr.co/edit/8t41rRnLYfhOF9oAfSUA
The reason this is necessary is because the number of columns is only calculated when masonry is initialized on the element or the container is resized and at this point we haven't got any bricks so it defaults to a single column.
If you don't want to use the 'resize' method (I don't think it's documented) then you could just call $element.masonry() but that causes a re-layout so you'd want to only call it when the first brick is added.
Edit: I've updated the plunker above to only call resize when the list grows above 0 length and to do only one "reload" when multiple bricks are removed in the same $digest cycle.
Directive code is:
angular.module('myApp.directives', [])
.directive("masonry", function($parse, $timeout) {
return {
restrict: 'AC',
link: function (scope, elem, attrs) {
elem.masonry({ itemSelector: '.masonry-brick'});
// Opitonal Params, delimited in class name like:
// class="masonry:70;"
//elem.masonry({ itemSelector: '.masonry-item', columnWidth: 140, gutterWidth: $parse(attrs.masonry)(scope) });
},
controller : function($scope,$element){
var bricks = [];
this.appendBrick = function(child, brickId, waitForImage){
function addBrick() {
$element.masonry('appended', child, true);
// If we don't have any bricks then we're going to want to
// resize when we add one.
if (bricks.length === 0) {
// Timeout here to allow for a potential
// masonary timeout when appending (when animating
// from the bottom)
$timeout(function(){
$element.masonry('resize');
}, 2);
}
// Store the brick id
var index = bricks.indexOf(brickId);
if (index === -1) {
bricks.push(brickId);
}
}
if (waitForImage) {
child.imagesLoaded(addBrick);
} else {
addBrick();
}
};
// Removed bricks - we only want to call masonry.reload() once
// if a whole batch of bricks have been removed though so push this
// async.
var willReload = false;
function hasRemovedBrick() {
if (!willReload) {
willReload = true;
$scope.$evalAsync(function(){
willReload = false;
$element.masonry("reload");
});
}
}
this.removeBrick = function(brickId){
hasRemovedBrick();
var index = bricks.indexOf(brickId);
if (index != -1) {
bricks.splice(index,1);
}
};
}
};
})
.directive('masonryBrick', function ($compile) {
return {
restrict: 'AC',
require : '^masonry',
link: function (scope, elem, attrs, MasonryCtrl) {
elem.imagesLoaded(function () {
MasonryCtrl.appendBrick(elem, scope.$id, true);
});
scope.$on("$destroy",function(){
MasonryCtrl.removeBrick(scope.$id);
});
}
};
});