ng-repeat动态完成后的Angular JS回调

时间:2016-02-02 02:14:51

标签: javascript jquery angularjs angularjs-directive angularjs-ng-repeat

有大量帖子显示如何根据指令设置回调函数,以便在ng-repeat函数完成后,您可以等待然后调用函数。例如,这是我的例子。

EXECUTE 'INSERT INTO ' || tablename_2 || ' VALUES (($1).*)' USING NEW ;

然后当它完成时,以下调用我的函数

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

完成后会成功调用我的函数

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

现在所有这些都完美无缺,并且第一次设置我的$ scope.Objects变量时也是如此。我的代码将等待所有对象完全呈现然后运行,完全是完美的。但是,如果在最初的所有内容后我再次更改$ scope.Objects,我的函数仍会运行,但它不会等待完成。它实际上可以通过控制台日志看到,第一轮它会在我进入指令之后但在实际发射之前暂停约半秒,但是在我的ng-repeat的后续更改中它不会暂停并简单地调用我的函数之前dom完成渲染。

这太烦人了,任何帮助都会很棒!

2 个答案:

答案 0 :(得分:2)

  

Angular的$ emit,$ broadcast和$ on在常见的“发布/订阅”设计模式下,或者可以做,您可以在其中发布事件并在其他地方订阅/取消订阅。 Angular事件系统非常出色,它使事情变得完美无缺(正如您所期望的那样!)但是它背后的概念并不是那么容易掌握而且你常常会想知道为什么事情不能像你一样工作以为他们可能。

     

使用$ scope。$ emit将触发$ scope范围内的事件。运用   $ scope。$ broadcast将在$ scope范围内触发一个事件。使用$ scope。$ on   我们是如何倾听这些事件的。

(reference)

我根据你的问题提供了两种解决方案。

解决方案一

<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);
    }
}]);

解决方案二

<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);
    });

}]);

答案 1 :(得分:2)

关于ng-repeat,您应该了解的一点是它尽可能重用DOM元素,因此如果您的转发器中有两个对象并且添加了第三个,则前两个元素将不会被重新渲染。只会渲染第三个,因此只能为新添加的对象调用一次指令的链接函数。

同样,如果您删除某个项目,您的指令的链接功能将不会再次运行。

观察此JSFiddle中的行为。