How do you trigger a reload in angular-masonry?

2019-03-28 06:43发布

I got Masonry to work in my AngularJS app using the angular-masonry directive but I want to be able to call a function or method in my controller that will trigger a reload of items in the container. I see in the source code (lines 101-104) there is a reload method but I'm not sure how to invoke that. Any ideas?

Thanks!

3条回答
走好不送
2楼-- · 2019-03-28 07:13

In case it's of use to someone in the future, Passy watches for an event called masonry.reload.

So, you can issue this event and Passy should call 'layout' on the masonry element, e.g. call

$rootScope.$broadcast('masonry.reload');

In my case, I had some third-party javascript decorating my bricks, so I needed to repaint after that was done. For reason (I was not able to figure out why), I needed to wrap the event broadcast in a timeout, I think the Passy scheduler was eating up the event and not repainting. E.g. I did:

$timeout(function () {
   $rootScope.$broadcast('masonry.reload');
   }, 5000);

This way you don't have to modify Passy directly.

查看更多
萌系小妹纸
3楼-- · 2019-03-28 07:29

The answer from @SebastianRiemer helped me.

But for future persons that need help try instead use the following

scope.$watch(function () {
    return element.height();
},
function (newValue, oldValue) {
    if (newValue != oldValue) {
        ctrl.scheduleMasonryOnce('reloadItems');
        ctrl.scheduleMasonryOnce('layout');
    }
});
查看更多
够拽才男人
4楼-- · 2019-03-28 07:33

I don't think you can trigger the reload() method directly, since it is part of the controller which is only visible within the directives.

You might either ...

A) trigger a reload directly of masonry via the element, jQuery-style

(see http://jsfiddle.net/riemersebastian/rUS9n/10/):

$scope.doReloadRelatively = function(e) {
    var $parent = $(e.currentTarget).parent().parent();
    $parent.masonry();
}

$scope.doReloadViaID = function() {
    $('#container').masonry();
}

B) or extend the directives yourself, i.e. add necessary watches on masonry-brick and call the reload() method within (depends on what use-case you have).

.directive('masonryBrick', function masonryBrickDirective() {
  return {
    restrict: 'AC',
    require: '^masonry',
    scope: true,
    link: {
      pre: function preLink(scope, element, attrs, ctrl) {
        var id = scope.$id, index;

        ctrl.appendBrick(element, id);
        element.on('$destroy', function () {
            console.log("masonryBrick > destroy")
          ctrl.removeBrick(id, element);
        });

        scope.$watch(function () {
            return element.height();
        },
        function (newValue, oldValue) {
            if (newValue != oldValue) {                    
                console.log("ctrl.scheduleMasonryOnce('layout');");
                ctrl.scheduleMasonryOnce('layout');
            }
        }
      );
      ...

In the code block above, I've simply added a watch on the element with the class 'masonry-brick' in order to trigger a reload of masonry whenever the elements' height changes.

I've created a jsFiddle for testing passys' angular-masonry myself, feel free to check it out!

http://jsfiddle.net/riemersebastian/rUS9n/10/

EDIT:

Just found a similar post on stackoverflow which could be another solution to this problem:

AngularJS Masonry for Dynamically changing heights

查看更多
登录 后发表回答