$watch не срабатывает в директиве после изменения в контроллере
У меня есть директива, которая в основном просто таймер обратного отсчета. Использование довольно просто, начните отсчет всякий раз, когда startFlag
Значение true, остановите подсчет, когда оно ложно, и вызовите функцию тайм-аута, когда время истечет:
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
Переменная правильно, когда данные из vm.timeRemaining
изменения (он инициализируется в 0 и затем обновляется, когда другой объект становится доступным).
Тем не менее, я хотел бы также предложить возможность продления времени, когда наступит условие тайм-аута. Но когда я обновляю 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
связанная переменная?
Обновить
Ниже приведена функция, которая извлекает задачу из моего текста данных (в основном это просто контейнер репозиториев). Как только обещание будет выполнено, vm.timeRemaining
обновляется и, в этой ситуации, правильно $watch
под редакцией директивы:
function getTask() {
return datacontext.task.loadForLevel(level)
.then(function(results) {
vm.task = results[0];
vm.timeRemaining = vm.task.time_limit;
})
;
}