ngModel обновлено после ngBlur

Я использую ввод datepicker ui-bootstrap с AngularJS. Он имеет ngModel и validatioon метод, связанный с событием ngBlur:

<input id="startDate" type="text" ng-model="myCtrl.startDate" ng-blur="myCtrl.validateDate()"/>

Метод проверки проверяет ngModel в соответствии с набором правил в контроллере и предупреждает при необходимости. Вот связанная часть контроллера:

var vm = this;
vm.startDate = new Date();
vm.minStartDate = new Date(2000,1,1);
vm.validateDate = function(){
    if(vm.startDate < vm.minStartDate)
        alert("Start date can't be earliar than 2000");
}

Проблема в том, что метод проверки выполняется до обновления модели. Пример сценария выглядит следующим образом:

Правило: дата начала не может быть раньше 2000 года .
При загрузке страницы значение startDate изначально устанавливается в сегодня. Пользователь выбирает 31.12.1999 из календаря, вызывается метод ngBlur. Однако ngModel еще не обновлен. Таким образом, проверка проверяет сегодняшнее значение и говорит ok. На самом деле, он должен был проверить значение ngModel с 31.12.1999 . Значение изменяется одновременно на входном виде, но в фоновом режиме оно устанавливается после запуска метода размытия. Насколько я знаю, двусторонняя привязка в AngularJS обычно служит для этой цели, но ngBlur должен быть исключением.

Я пробовал много вещей, таких как;

  • Добавление параметров ng-model В компонент:

    ng-model-options="{ updateOn: 'blur' }"

  • Использование связывания pre и post путем изменения входного элемента

  • Использование ng-change вместо ng-blur

Однако ничего из вышеперечисленного не работает, и все равно ng-blur запускается до обновления модели.

3 ответа

  1. Простой способ убедиться в том, что проверка срабатывает только после обновления значения,-вызвать ее на NG-change вместо ng-blur. Таким образом, вы уверены, что контроллер оценивает только после того, как значение ng-модели было обновлено.

  2. Попробуйте создать собственный валидатор (директива)

    app.directive('integer', function() {
      return {
        require: 'ngModel',
        link: function(scope, elm, attrs, ctrl) {
          ctrl.$validators.integer = function(modelValue, viewValue) {
            if (ctrl.$isEmpty(modelValue)) {
              // consider empty models to be valid
              return true;
            }
    
            if (INTEGER_REGEXP.test(viewValue)) {
              // it is valid
              return true;
            }
    
            // it is invalid
            return false;
          };
        }
      };
    });
    

    Проверьте этот пример
    https://plnkr.co/edit/SZoBKakhzIq5wRoCvEyG?p=preview

  3. Я нашел решение, вручную обновив значения внутри контроллера. Очевидно, AngularJS не будет обновлять модель со значением внутри элемента HMTL, пока не будет запущено событие blur. Поэтому лучше написать метод для его обновления.

    Я могу получить доступ к значению внутри элемента следующим образом:

    vm.startDate = angular.element('#startDate').val();
    

    Тогда я могу обернуть это с помощью метода:

    vm.updateModels() = function(){
        vm.startDate = angular.element('#startDate').val();
    }
    

    Наконец, я просто называю это на самом первом из моих событий blur:

    vm.validateDate = function(){
        //Update first
        vm.updateModels();
        //Then validate
        if(vm.startDate < vm.minStartDate)
            alert("Start date can't be earliar than 2000");
    }
    

    Ta tammm, теперь я могу проверить значения updatet!