Предотвратить асинхронный уникальный валидатор для проверки одного и того же значения только при редактировании?

У меня есть форма AngularJS, в которой есть настраиваемый валидатор для проверки серверной частью сервера, является ли входное значение уникальным или нет. Уникальная проверка выполняется директивой mob-async-validate-unique в приведенном ниже примере.

Форма выглядит примерно так:

<form class="form-floating" novalidate="novalidate" ng-submit="saveItem(item)">
    <div class="form-group filled">
        <label class="control-label">Key</label>
        <input type="text" class="form-control" ng-model="item.Key" mob-async-validate-unique >
    </div>

    <div class="form-group">
        <button type="submit" class="btn btn-lg btn-primary">Save</button>
    </div>

</form>

Я хочу использовать одну и ту же форму для оба добавления и редактирования модели, которую я поместил на $scope.

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

  1. Измените значение поля, а затем отредактируйте его до исходного значения.
  2. Отправьте форму, ничего не меняя

Каков наилучший способ добиться этого? Наивный способ, о котором я могу думать, заключается в том, что мне придется сохранить исходное значение в переменной $scope.originalValue, а затем добавить атрибут к уникальному проверенному элементу, чтобы назвать эту переменную. В валидаторе я прочитаю это значение из $scope и сравню его с текущим значением, чтобы валидатор принял его, когда два значения совпадают. Я иду вперед и реализую это.

Я использую уникальный валидатор общим способом в нескольких местах (да, в элементе <input> используется еще несколько атрибутов, которые я не включил в пример кода для простоты и удобочитаемости), и мне нужно, чтобы валидатор полностью функционировал на он собственный, и в идеале я хочу, чтобы контроллер $scope был вне поля зрения, чтобы я мог использовать собственный асинхронный валидатор в любом случае / где угодно.


person Dhiraj Gupta    schedule 29.10.2015    source источник


Ответы (2)


В зависимости от используемой вами версии angularjs нет абсолютно никакой необходимости в написании собственного асинхронного валидатора. В Angular есть встроенный способ сделать это. Проверьте https://docs.angularjs.org/api/ng/type/ngModel.NgModelController

Когда вы используете $asyncValidator, как описано в документации, он проверяет ваш API только в том случае, если все остальные проверки прошли успешно.

** РЕДАКТИРОВАТЬ ** Что касается вашей проблемы с асинхронной проверкой при редактировании существующей записи в вашей базе данных, я предлагаю следующее.

var originalData = {};
if(editMode) {
  originalData = data.from.your.API;
} 
$scope.formData = angular.copy(orignalData);

// in your async validator
if(value && value !== orginalData(key)) {
  //do async validation
} else if(value == originalData(key)) {
  return true;  //field is valid
}
person Kyoss    schedule 29.10.2015
comment
Предоставленная вами ссылка дает пример, но не для повторного использования. Создание директивы валидатора - единственный способ (я знаю) сделать это. Кроме того, всегда будет требоваться код для разрешения/отклонения. Да, я знаю, что асинхронные валидаторы срабатывают только после проверки обычных валидаторов, таких как required, number и т. д. Пожалуйста, прочитайте вопрос, мне нужно, чтобы валидатор не отклонял в режиме редактирования, когда значение одинаково. - person Dhiraj Gupta; 29.10.2015
comment
добавил пример для вашего случая - person Kyoss; 02.11.2015

вот моя директива для решения проблемы

  • проверить, нажал ли пользователь клавишу
  • если model value то же, что и initialValue. Асинхронная проверка не будет применяться

    export default function ($http, API_URL, $q) {
      "ngInject";
      return {
        require: 'ngModel',
        restrict: 'A',
        scope: {
          asyncFieldValidator: '@',
          initialValue: '@'
        },
        link: ($scope, element, attrs, ngModel) => {
          const apiUrl = `${API_URL}${$scope.asyncFieldValidator}`;
    
          element.on('keyup', e => {
            ngModel.$asyncValidators.uniq = (modelValue, viewValue) => {
              const userInput = modelValue || viewValue;
              const checkInitial = $scope.initialValue === userInput;
              return !checkInitial
                ? $http.get(apiUrl + userInput)
                  .then(res => res.status === 204 ? true : $q.reject())
                : $q.resolve(`value is same`)
            }
          });
        }
      }
    }
    
person Yuriy Yakovenko    schedule 13.12.2016