Angular指令中的$ observe仅在第一次属性更改时触发

时间:2014-05-29 18:59:48

标签: angularjs angularjs-directive

我正在尝试编写自定义指令,但该指令正在观察的属性似乎只是在初始范围更改时发生了变化。之后,视图中的绑定(使用Firebug观察)不再更新。这似乎是一个范围问题,但我没有想法。

JSFiddle Link显示带有问题的代码:http://jsfiddle.net/catalyst156/2gp78/(下面的小提琴的内容,但它可能有助于弄乱小提琴本身)。

控制器:

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js></script>
<script>
var myApp = angular.module('myApp', []);

myApp.directive('testDirective', function () {
    return {
        restrict: 'A',
        replace: true,
        scope: {
            toggle: '@'
        },
        link: function (scope, element, attrs) {
            console.log('...linking testDirective...');

            attrs.$observe('toggle', function (value) {
                console.log('directive: toggle observer');
                if ('true' === value) {
                    console.log('directive: toggle=true');
                } else {
                    console.log('directive: toggle=false');
                }
            });
        }
    };
});

myApp.controller('myCtrl', ['$scope', '$log', function ($scope, $log) {
    $scope.toggleState = false;

    $scope.testToggle = function () {
        $scope.toggleState = true;
        $log.log('controller: toggleState=' + $scope.toggleState);

        setTimeout(turnToggleOff, 2000);
    };

    function turnToggleOff() {
        $scope.toggleState = false;
        $log.log('controller: toggleState=' + $scope.toggleState);
    }
}]);

HTML:

<div ng-app="myApp">
    <div ng-controller="myCtrl">
        <div test-directive toggle={{toggleState}}></div>
        <button ng-click="testToggle()">Toggle Me</button>
    </div>
</div>

控制台输出:

1: ...linking testDirective...
2: directive: toggle observer
3: directive: toggle=false
4: controller: toggleState=true
5: directive: toggle observer
6: directive: toggle=true
7: controller: toggleState=false 

我可以看到链接正常工作,初始状态按预期设置为false(第1-3行)。单击该按钮,并向观察者通知更改(第4-6行)。但是,当计时器到期并且'toggleState = false'时,观察者永远不会接受该更改。 (按下多个按钮仅显示控制器的控制台输出,并且观察者永远不会再次触发)。

1 个答案:

答案 0 :(得分:2)

问题是角度不知道setTimeout()所做的更改。换句话说,setTimeout()不会触发$digest周期。 Angular提供了与setTimeout()完全相同的$timeout,但它会触发$digest,因此Angular会看到更改(这会导致您的observe触发)。

所以只需传入$timeout依赖项:

myApp.controller('myCtrl', ['$scope', '$log', '$timeout', function ($scope, $log, $timeout) {...}

切换你的超时电话:

$timeout(turnToggleOff, 2000);

这里是updated fiddle