2015-09-03 6 views
3

У меня есть 2 даты - начало и конец. Я хочу подтвердить (и заверить) начало < конец. Я получаю уведомление, что они меняются с помощью $ watch, а затем я иду и меняю их, чтобы убедиться, что условие выполнено, но затем он снова запускает $ watch, а затем я получаю максимальные итерации, достигнутые в $ digest, и все идет на юг.

Так что мой вопрос: как изменить переменные, которые наблюдаются внутри $watch, не вызывая бесконечного цикла. (Помимо того больше проверок и изменять их только тогда, когда они на самом деле должно быть изменено)

Вот мой код:

var TIME_DAY = 1000 * 60 * 60 * 24; 

$scope.$watch('timeFilter.startTime', function() { 
    validateStartEndTime(); 
},true); 

$scope.$watch('timeFilter.endTime', function() { 
    validateStartEndTime(); 
},true); 

function validateStartEndTime() { 
    if ($scope.timeFilter.startTime != null && $scope.timeFilter.endTime != null) { 
     // Remove all seconds 
     if ($scope.timeFilter.startTime.getSeconds() > 0) 
      $scope.timeFilter.startTime.setSeconds(0); 
     if ($scope.timeFilter.endTime.getSeconds() > 0) 
      $scope.timeFilter.endTime.setSeconds(0); 
     if ($scope.timeRange.minTime.getSeconds() > 0) 
      $scope.timeRange.minTime.setSeconds(0); 
     if ($scope.timeRange.maxTime.getSeconds() > 0) 
      $scope.timeRange.maxTime.setSeconds(0); 

     // When start time isn't before end time 
     if ($scope.timeFilter.startTime >= $scope.timeFilter.endTime) { 
      // We want to increase end time by 1 minute, if possible - do it. Else - reduce start time by 1 minute 
      if ($scope.timeFilter.endTime < $scope.timeRange.maxTime) { 
       $scope.timeFilter.endTime.setMinutes($scope.timeFilter.startTime.getMinutes() + 1); 
      } else { 
       $scope.timeFilter.startTime.setMinutes($scope.timeFilter.startTime.getMinutes() - 1); 
      } 
     } 

     // Start time before min time 
     if ($scope.timeFilter.startTime < $scope.timeRange.minTime) { 
      $scope.timeFilter.startTime = $scope.timeRange.minTime; 
      if ($scope.timeFilter.endTime <= $scope.timeFilter.startTime) { 
       $scope.timeFilter.endTime = $scope.timeFilter.startTime; 
       $scope.timeFilter.endTime.setMinutes($scope.timeFilter.endTime.getMinutes() + 1); 
      } 
     } 

     // End time after max time 
     if ($scope.timeFilter.endTime > $scope.timeRange.maxTime) { 
      $scope.timeFilter.endTime = $scope.timeRange.maxTime; 
      if ($scope.timeFilter.startTime >= $scope.timeFilter.endTime) { 
       $scope.timeFilter.startTime = $scope.timeFilter.endTime; 
       $scope.timeFilter.startTime.setMinutes($scope.timeFilter.startTime.getMinutes() - 1); 
      } 
     } 
    } 
} 
+0

просто установите переменную флага. установите флаг, когда ваше условие истинно, и разрешите любое действие, если флаг еще не установлен. –

+0

Я думаю, вам будет лучше обслуживать использование угловых завершенных событий DOM для проверки даты, например 'ng-blur',' ng-change' ... – tiledcode

+0

Я бы пошел с логической переменной, например. manualChange. Это должно быть установлено в false в начале validateStartEndTime. Затем в каждом часе, если manualChange имеет значение true, вызывается validateStartEndTime, иначе установите для параметра ManualChange значение true и return. – dchar

ответ

1

Честно говоря, я бы предпочел, чтобы найти способ, чтобы избежать, чтобы изменить переменную, которая постоянно наблюдал. Но, если вы действительно этого хотите, вы можете отменить регистрацию своей функции $ watch, когда вам нужно изменить наблюдаемые переменные, а затем снова зарегистрировать функцию $ watch.

Чтобы отменить регистрацию функции $ watch, вам просто нужно получить ссылку и вызвать, когда вам нужно.

var myWatch = $scope.$watch('timeFilter.startTime', function() { 
    validateStartEndTime(); 
},true); 
myWatch(); // It will deregister it. 

Помните, что иногда, когда вы впервые смотрите переменную, она автоматически активирует функцию. Мое предложение состоит в том, чтобы всегда проверять, действительно ли старая переменная изменена.

var myWatch = $scope.$watch('timeFilter.startTime', function (newValue, oldValue) { 
    if(newValue === oldValue){ 
     return; 
    } 
    validateStartEndTime(); 
},true); 

Я надеюсь, что это сработает для вас. К сожалению, я не могу проверить этот код прямо сейчас.

+0

Проверка oldvalue === newvalue велик. Как мне пойти на отмену регистрации? Я вызываю myWatch из $ watch? А потом, когда я перерегистрирую его? – AlexD

+0

Вы регистрируетесь после изменения переменной, которая не наблюдалась на мгновение. – Daniele

0

я объединил предложения и советы от всех, кто ответил на что-то вроде этого:

$scope.$watch('timeFilter.startTime', function(newValue, oldValue) { 
    if (newValue === oldValue) return; 
    validateStartEndTime(); 
}, true); 

$scope.$watch('timeFilter.endTime', function(newValue, oldValue) { 
    if (newValue === oldValue) return; 
    validateStartEndTime(); 
}, true); 

function validateStartEndTime(startChanged) { 
    if ($scope.timeFilter.startTime == null || $scope.timeFilter.endTime == null) return; 
    var tempStart = new Date($scope.timeFilter.startTime), tempEnd = new Date($scope.timeFilter.endTime); 
    if ($scope.timeRange.minTime && $scope.timeRange.maxTime) { 
     // Logic start 

     // Logic ends 

     if ($scope.timeFilter.startTime !== tempStart) 
      $scope.timeFilter.startTime = tempStart; 
     if ($scope.timeFilter.endTime !== tempEnd) 
      $scope.timeFilter.endTime = tempEnd; 
    } 
} 

Таким образом, я убедиться, что я делаю, как небольшие изменения, как это возможно. Я открыт для предложений, если у кого-то есть

Смежные вопросы