Angular JS callback after ng-repeat is completed dynamically

巧了我就是萌 提交于 2019-12-10 23:07:57

问题


There are tons of posts showing how to have callback functions based on a directive so that when an ng-repeat function is finished you can wait and then call a function. For example here is my example.

<div ng-repeat="Object in Objects" class="objectClass" on-finish-render>{{Object.Overlay}</div>

Then when it is completed the following calls my function

.directive('onFinishRender', function ($timeout) {
    return {
        restrict: 'A',
        link: function (scope, element, attr) {
            if (scope.$last === true) {
                $timeout(function () {
                    scope.$emit('ngRepeatFinished');
                }, 0);
            }
        }
    }
});

This successfully calls my function below when it is completed

$scope.$on('ngRepeatFinished', function(ngRepeatFinishedEvent) {
    //my code goes here
}

Now all of that works perfectly and as intended the first time I set my $scope.Objects variable. My code will wait until all objects are fully rendered and then runs, literally perfect. However if after the initial everything I change $scope.Objects again, my function will still run but it will NOT wait for the completion. Its actually visible with console logs, the first go round it will pause for about half a second after I go into the directive but before the actual emit, but on subsequent changes to my ng-repeat it does not pause and simply calls my function before the dom is finished rendering.

This is super annoying and any help would be great!


回答1:


One thing you should understand about ng-repeat is that it reuses DOM elements whenever possible, so if you have two objects in your repeater and you add a third, the first two elements will not be re-rendered. Only the third will be rendered, thus your directive's link function will only be called once for the newly-added object.

Similarly, if you remove an item, your directive's link function will not be run again.

Observe the behavior in this JSFiddle.




回答2:


Angular’s $emit, $broadcast and $on fall under the common “publish/subscribe” design pattern, or can do, in which you’d publish an event and subscribe/unsubscribe to it somewhere else. The Angular event system is brilliant, it makes things flawless and easy to do (as you’d expect!) but the concept behind it isn’t so simple to master and you can often be left wondering why things don’t work as you thought they might.

Using $scope.$emit will fire an event up the $scope. Using $scope.$broadcast will fire an event down the $scope. Using $scope.$on is how we listen for these events.

(reference)

I have provided two solution according to your problem.

Solution One

<div ng-controller="MyCtrl">
    <div ng-repeat="Object in Objects" class="objectClass" on-finish-render isolated-expression-foo="updateItem(item,temp)">{{Object|json}</div>
</div>

var app = angular.module('app', []);    
app.directive('onFinishRender', function () {
    return {
        restrict: 'A',
        scope: {
            isolatedExpressionFoo: '&'
        },
        link: function (scope, element, attr) {
            if (scope.$parent.$last) {
                scope.isolatedExpressionFoo({ temp: "some value" });
            }
        }
    };
});

app.controller('MyCtrl', ['$scope', function ($scope) {

    $scope.Objects = [{ id: 1, value: "test" }, { id: 2, value: "TEst2" }];

    $scope.updateItem = function (item, temp) {
        console.log("Item param " + item.id);
        console.log("temp param " + temp);
    }
}]);

Solution Two

<div ng-controller="MyCtrl">
     <div ng-repeat="Object in Objects" class="objectClass" on-finish-render>{{Object|json}</div>
</div>

var app = angular.module('app', []);    
app.directive('onFinishRender', function ($rootScope) {
    return {
        restrict: 'A',
        link: function (scope, element, attr) {
            if (scope.$last) {
                $rootScope.$broadcast("ngRepeatFinished", { temp: "some value" });
            }
        }
    };
});

app.controller('MyCtrl', ['$scope', function ($scope) {

    $scope.Objects = [{ id: 1, value: "test" }, { id: 2, value: "TEst2" }];

    $scope.$on('ngRepeatFinished', function (temp) {
        console.log("Item param " + temp);
    });

}]);


来源:https://stackoverflow.com/questions/35143922/angular-js-callback-after-ng-repeat-is-completed-dynamically

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!