$ watch在控制器更改后不在触发器中触发

时间:2014-05-13 15:45:27

标签: angularjs angularjs-directive javascript-databinding

我有一个基本上只是倒数计时器的指令。用法非常简单,只要startFlag为真,就开始倒计时,当它为假时停止计数,并在时间用完时调用超时函数:

app.directive('countdownTimer', [ '$interval', 
    function($interval) {
        var directive = {
            restrict: 'E',
            templateUrl: 'app/common/countdownTimer.html',
            scope: {
                timeAllotted: '=',
                startFlag: '=',
                timeoutCallback: '='
            },
            link: link
        };
        return directive;

        function link(scope, element, attrs) {
            var timeLeft;

            // Set watch on time allotted
            scope.$watch('timeAllotted', function(newValue) {
                timeLeft = newValue;
                scope.minutes = getMinutes(timeLeft);
                scope.seconds = getSeconds(timeLeft);
            });

            // Set watch on start flag
            scope.$watch('startFlag', function(newValue) {
                if(newValue) {
                    scope.timer = $interval(tickFunction, 1000);
                } else {
                    $interval.cancel(scope.timer);
                }
            });

            function getFormattedTimeValue(val) {
                if(val < 10) {
                    val = '0' +  val;
                }
                return val;
            }

            function getMinutes(secs) {
                return getFormattedTimeValue(parseInt(secs / 60));
            }

            function getSeconds(secs) {
                return getFormattedTimeValue(secs % 60);
            }

            function tickFunction(triggerTimeout) {
                timeLeft = timeLeft - 1;
                scope.minutes = getMinutes(timeLeft);
                scope.seconds = getSeconds(timeLeft);
                if(timeLeft <= 0) {
                    scope.timeoutCallback();
                    scope.startFlag = false;
                }
            }
        }
    }
]);

我的问题是上面的timeAllotted上的手表有效,但只是第一次。它由从远程数据源加载的对象的属性设置:

<countdown-timer
    data-time-allotted="vm.timeRemaining" 
    data-start-flag="vm.taskStarted" 
    data-timeout-callback="vm.taskTimeout">
</countdown-timer>

所有这一切都很有效。当来自timeLeft的数据发生变化时(该变量初始化为0,然后在另一个对象变为可用时更新),该指令会正确更新其本地vm.timeRemaining变量。

但是,我还希望在超时条件发生后提供延长时间的选项。但是当我在超时条件之后更新vm.timeRemaining时,不会触发指令上的$watch

这是我目前尝试更新控制器的剩余时间:

function extendTime() {
    // This should reset the clock back to it's starting time, 
    // but it doesn't change!
    vm.timeRemaining = vm.task.time_limit;

    vm.hasAccess = true;
    dismissModal();

    // Added timeout so I could try $scope.$apply().. didn't help
    $timeout(function() {

        $scope.$apply();

        // This confirms that vm.timeRemaining is updating here, but the 
        // $watch on timeAllotted isn't firing in the directive
        console.log('timeRemaining updated');
        console.log(vm.timeRemaining);

        startTask();
    }, 50);

}

对于它的价值,任务超时并没有做太多有趣的事情:

function taskTimeout() {
    // Cancels timer
    pauseTask();
    // Synchronizes data with API
    syncTick();
    // Opens a modal
    vm.modalInstance = $modal.open({
        templateUrl: 'app/common/timeoutModal.html',
        scope: $scope
    });
}

我的指令vm.timeRemaining上的extendTime绑定变量无法识别我的控制器$watch函数中更新timeAllotted的原因吗?

更新

下面是从我的datacontext中检索任务的函数(它基本上只是一个存储库的容器)。一旦承诺得到解决,vm.timeRemaining就会更新,在这种情况下,指令正确$watch

function getTask() {
    return datacontext.task.loadForLevel(level)
        .then(function(results) {
            vm.task = results[0];
            vm.timeRemaining = vm.task.time_limit;
        })
    ;
}

0 个答案:

没有答案