I am developing an \"art gallery\" app.
Feel free to pull down the source on github and play around with it.
Plunker with full
This is not exacly what you are looking for (prepend and append), but should be just what you are looking for:
http://plnkr.co/edit/dmuGHCNTCBBuYpjyKQ8E?p=preview
Your version of the directive triggers reload for every brick. This version triggers only reload only once for the whole list change.
The approach is very simple:
bricks in parent masonry controller$watch for changes in the registered bricks and fire masonry('reload')brick from bricks registry when you are removing the element - $on('$destroy')You can extend this approach to do what you wanted (use prepend and append) but I don't see any reason why you would want to do that. This also would be much more complicated, since you would have to manually track the order of the elements. I also don't belive it would be any faster - on the contrary it may be slower, since you would have to trigger multiple append/prepend if your changes a lot of bricks.
I am not quite sure, but I guess you could use ng-animate for this (the JavaScript animation version)
We have implemented something similar for tiling events in our calendar app. This solution turned out to be the fastest. If anyone has better solution, I'd love to see that.
For those who want to se the code:
angular.module('myApp.directives', [])
.directive("masonry", function($parse) {
return {
restrict: 'AC',
controller:function($scope,$element){
// register and unregister bricks
var bricks = [];
this.addBrick = function(brick){
bricks.push(brick)
}
this.removeBrick = function(brick){
var index = bricks.indexOf(brick);
if(index!=-1)bricks.splice(index,1);
}
$scope.$watch(function(){
return bricks
},function(){
// triggers only once per list change (not for each brick)
console.log('reload');
$element.masonry('reload');
},true);
},
link: function (scope, elem, attrs) {
elem.masonry({ itemSelector: '.masonry-brick'});
}
};
})
.directive('masonryBrick', function ($compile) {
return {
restrict: 'AC',
require:'^masonry',
link: function (scope, elem, attrs,ctrl) {
ctrl.addBrick(scope.$id);
scope.$on('$destroy',function(){
ctrl.removeBrick(scope.$id);
});
}
};
});
Edit: there is one thing I forgot about (loading images) - just call 'reload' when all images were loaded. Ill try to edit the code later.