首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >AngularJS:基于链接输入字段的自定义验证

AngularJS:基于链接输入字段的自定义验证
EN

Stack Overflow用户
提问于 2015-11-09 16:01:21
回答 2查看 514关注 0票数 0

有三个输入域

代码语言:javascript
复制
<input type="text" name="foo1" ng-model="data.input1"/>
<ng-messages for="forms.myForm.foo1" role="alert">
    <ng-message when="oneRequired"> Please set foo1 (or foo2 or foo3) </ng-message>
<ng-messages>

<input type="text" name="foo2" ng-model="data.input2"/>
<ng-messages for="forms.myForm.foo2" role="alert">
    <ng-message when="oneRequired"> Please set foo2 (or foo1 or foo3) </ng-message>
<ng-messages>

<input type="text" name="foo3" ng-model="data.input3"/>
<ng-messages for="forms.myForm.foo3" role="alert">
    <ng-message when="oneRequired"> Please set foo3 (or foo1 or foo2) </ng-message>
<ng-messages>

我希望保证至少设置了一个输入字段的值。在这种情况下,不仅当前的验证字段$error应该计算为'false‘,而且所有其他字段也应该计算为’false‘。所有消息都应该消失。

我的第一个想法是使用一个指令和一个唯一的id将字段链接在一起:

代码语言:javascript
复制
<input type="text" name="foo1" ng-model="data.input1" one-required="i1_i2_i3_link_identifier/>

也许我可以使用一个(单例)服务来注册控制器和当前值。但是我没有一个想法来确保所有链接的控制器(在指令中使用)在验证错误时都被更新。

EN

回答 2

Stack Overflow用户

发布于 2015-11-09 16:23:39

我强烈推荐使用https://github.com/turinggroup/angular-validator指令。它非常灵活,可以很容易地设置您的自定义验证器。通过这个指令,我可以去掉ng-message并大大清理我的html代码。

您可以在控制器或服务中设置一个自定义验证器,以便在整个站点中使用。

代码语言:javascript
复制
            <input  type = "text"
                    name = "firstName"
                    class = "form-control"
                    ng-model = "form.firstName"
                    validator = "myCustomValidator(form.firstName)"
                    validate-on="dirty"
                    required></div>

这里有一个插入器和代码给你:http://plnkr.co/edit/X5XdYYekT4YZH6xVBftz?p=preview,正如你所看到的,这非常笨重,有很多代码。使用angular验证器,您可以将代码减少为内联在输入中,并添加一个控制器函数。

代码语言:javascript
复制
   <form name="myForm">
      <input type="text" name="foo1" ng-model="data.input1" required/>
      <div ng-if="myForm.foo1.$error.required && myForm.foo2.$error.required && myForm.foo3.$error.required" class="error">
        <ng-messages for="myForm.foo1" role="alert">
          <ng-message="required"> Please set foo1 (or foo2 or foo3) </ng-message>
        </ng-messages>
      </div>
      <br/>
      <input type="text" name="foo2" ng-model="data.input2" required/>
      <div ng-if="myForm.foo1.$error.required && myForm.foo2.$error.required && myForm.foo3.$error.required" class="error">
        <ng-messages for="myForm.foo2" role="alert">
          <ng-message="required"> Please set foo2 (or foo2 or foo3) </ng-message>
        </ng-messages>
      </div>
      <br/>
      <input type="text" name="foo3" ng-model="data.input3" required/>
      <div ng-if="myForm.foo1.$error.required && myForm.foo2.$error.required && myForm.foo3.$error.required" class="error">
        <ng-messages for="myForm.foo3" role="alert">
          <ng-message="required"> Please set foo3 (or foo2 or foo3) </ng-message>
        </ng-messages>
      </div>
      <br/>
    </form>  
票数 1
EN

Stack Overflow用户

发布于 2015-11-13 15:38:26

我使用一个保存这些值的中央服务和一个回调注册表解决了这个问题。当输入发生变化时,回调函数会一直被调用(使用监视器):

代码语言:javascript
复制
angular.module('myApp', []);

    angular.module('myApp').controller('myFormController', function($scope) {
          $scope.data = {
            i1: "remove",
            i2: "all",
            i3: "values"
          };
    });

    angular.module('myApp').factory('oneRequiredService', function() {
          var service = {};
          var container = {};
          var observerCallbacks = {};

          var isValid = function(groupId) {
            var valid = false;

            var modelStates = container[groupId];
            angular.forEach(modelStates, function(modelValid) {
              valid = valid || (modelValid ? true : false);
            });
            return valid;
          };

          var isRegistered = function(groupId) {
            return container.hasOwnProperty(groupId);
          };

          var notifyAll = function(key) {
            var valid = isValid(key);
            if (isRegistered(key)) {
              angular.forEach(observerCallbacks[key], function(callback, index) {
                callback(valid);
              });
            };
          };

          service.register = function(groupId, scopeId, callback) {
            this.updateValue(groupId, scopeId, undefined);
            if (callback) {
              this.registerCallback(groupId, callback);
            }
          };

          service.registerCallback = function(groupId, callback) {
            if (callback) {
              observerCallbacks[groupId] = observerCallbacks[groupId] || [];
              observerCallbacks[groupId].push(callback);
            };
          };

          service.updateValue = function(groupId, scopeId, value) {
            container[groupId] = container[groupId] || {};
            container[groupId][scopeId] = value;
            notifyAll(groupId);
          };

          return service;
        });

        angular.module('myApp').directive('oneRequired', function(oneRequiredService) {
          return {
            restrict: "A",
            require: 'ngModel',
            scope: true,
            link: function(scope, element, attrs, ctrl) {

              var modelAttr = attrs["ngModel"];
              
              var linkIdentifier = attrs["oneRequired"];
              
              var updateCurrentState = function(isValid) {
                scope._valid = isValid;
              };

              scope.$watch(modelAttr, function(newVal, oldVal) {
                oneRequiredService.updateValue(linkIdentifier, scope.$id, newVal);
              });

              scope.$watch('_valid', function(newVal, oldVal) {
                ctrl.$setValidity('oneRequired', newVal);
              });

              oneRequiredService.register(linkIdentifier, scope.$id, updateCurrentState);
            }
          }
        });
代码语言:javascript
复制
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.21/angular.min.js"></script>

<body ng-app="myApp">
      <form ng-controller="myFormController" name="forms.myForm">

        <label for="i_1">i_1</label>
        <input id="i_1" name="i1" type="text" one-required="foo-bar" ng-model="data.i1" />
        <span> i1-err-one-required: {{forms.myForm.i1.$error.oneRequired}} </span> <br>
           
        <label for="i_2">i_2</label>
        <input id="i_2" name="i2"  type="text" one-required="foo-bar" ng-model="data.i2"/>
        <span> i2 err-one-required:  {{forms.myForm.i2.$error.oneRequired}} </span> <br>
           
        <label for="i_3">i_3</label>
        <input id="i_3" name="i3" type="text" one-required="foo-bar" ng-model="data.i3"/>
        <span> i3-err-one-required: {{forms.myForm.i3.$error.oneRequired}} </span> <br>
      </form>
    </body>

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33604720

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档