Calling a function when ng-repeat has finished

前端 未结 10 1616
面向向阳花
面向向阳花 2020-11-22 02:28

What I am trying to implement is basically a \"on ng repeat finished rendering\" handler. I am able to detect when it is done but I can\'t figure out how to trigger a functi

相关标签:
10条回答
  • 2020-11-22 03:04
    var module = angular.module('testApp', [])
        .directive('onFinishRender', function ($timeout) {
        return {
            restrict: 'A',
            link: function (scope, element, attr) {
                if (scope.$last === true) {
                    $timeout(function () {
                        scope.$emit(attr.onFinishRender);
                    });
                }
            }
        }
    });
    

    Notice that I didn't use .ready() but rather wrapped it in a $timeout. $timeout makes sure it's executed when the ng-repeated elements have REALLY finished rendering (because the $timeout will execute at the end of the current digest cycle -- and it will also call $apply internally, unlike setTimeout). So after the ng-repeat has finished, we use $emit to emit an event to outer scopes (sibling and parent scopes).

    And then in your controller, you can catch it with $on:

    $scope.$on('ngRepeatFinished', function(ngRepeatFinishedEvent) {
        //you also get the actual event object
        //do stuff, execute functions -- whatever...
    });
    

    With html that looks something like this:

    <div ng-repeat="item in items" on-finish-render="ngRepeatFinished">
        <div>{{item.name}}}<div>
    </div>
    
    0 讨论(0)
  • 2020-11-22 03:07

    The other solutions will work fine on initial page load, but calling $timeout from the controller is the only way to ensure that your function is called when the model changes. Here is a working fiddle that uses $timeout. For your example it would be:

    .controller('myC', function ($scope, $timeout) {
    $scope.$watch("ta", function (newValue, oldValue) {
        $timeout(function () {
           test();
        });
    });
    

    ngRepeat will only evaluate a directive when the row content is new, so if you remove items from your list, onFinishRender will not fire. For example, try entering filter values in these fiddles emit.

    0 讨论(0)
  • 2020-11-22 03:15

    Please have a look at the fiddle, http://jsfiddle.net/yNXS2/. Since the directive you created didn't created a new scope i continued in the way.

    $scope.test = function(){... made that happen.

    0 讨论(0)
  • 2020-11-22 03:18

    If you’re not averse to using double-dollar scope props and you’re writing a directive whose only content is a repeat, there is a pretty simple solution (assuming you only care about the initial render). In the link function:

    const dereg = scope.$watch('$$childTail.$last', last => {
        if (last) {
            dereg();
            // do yr stuff -- you may still need a $timeout here
        }
    });
    

    This is useful for cases where you have a directive that needs to do DOM manip based on the widths or heights of the members of a rendered list (which I think is the most likely reason one would ask this question), but it’s not as generic as the other solutions that have been proposed.

    0 讨论(0)
提交回复
热议问题