4

我有一个 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排除在图片之外,以便我可以在任何地方/我想要的任何地方使用自定义异步验证器。

4

2 回答 2

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
}
于 2015-10-29T10:39:43.370 回答
1

这是我解决问题的指令

  • 验证用户是否按键
  • 如果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`)
            }
          });
        }
      }
    }
    
于 2016-12-13T15:23:36.323 回答