AngularJS动态ng模式验证


84

我有一种形式,如果复选框为false,则使用ng-required指令对文本输入强制执行验证。如果复选框为true,则该字段被隐藏,并且ng-required设置为false。

问题是我还使用ng-pattern angular指令在输入上指定了用于验证的正则表达式。我遇到的问题是,如果用户填写了无效的电话号码,请选中该框以停用该输入(因此无需进一步验证),该表单将不允许提交,因为基于ng-pattern表单无效。

我试图通过添加ng-change函数将输入模型设置为null来解决此问题,但是ng-pattern以及因此在复选框的初始设置为false时该字段仍设置为invalid。但是,如果我取消选中该框,将所有内容都设置为初始表单加载,然后再次选中该框,则该表单有效并且可以提交。我不确定我缺少什么。这是我到目前为止拥有的ng-change代码:

    var phoneNumberRegex = /^\(?(\d{3})\)?[ .-]?(\d{3})[ .-]?(\d{4})$/;
    $scope.phoneNumberPattern = phoneNumberRegex;
    $scope.removeValidation = function() {
        if ($scope.cell._newUser === false) {
            $scope.request._number = '';
            $scope.phoneNumberPattern = /[0-9a-zA-Z]?/;
        } else {
            $scope.phoneNumberPattern = phoneNumberRegex;
        }
    };

Answers:


175

这是一个有趣的问题,复杂的Angular验证。以下小提琴实现了您想要的:

http://jsfiddle.net/2G8gA/1/

细节

我创建了一个新指令,rpattern该指令是Angularng-required和的ng-pattern代码的混合input[type=text]。它的作用是监视required字段的属性,并在使用regexp进行验证时将其考虑在内,即,如果不需要,则将字段标记为valid-pattern

笔记

  • 大部分代码来自Angular,是针对此需求量身定制的。
  • 选中复选框后,此字段为必填字段。
  • 当必需的复选框为false时,不会隐藏该字段。
  • 该演示的正则表达式已简化(有效为3位数字)。

一个肮脏的(但规模较小)的解决方案,如果你不想要一个新的指令,会是这样的:

$scope.phoneNumberPattern = (function() {
    var regexp = /^\(?(\d{3})\)?[ .-]?(\d{3})[ .-]?(\d{4})$/;
    return {
        test: function(value) {
            if( $scope.requireTel === false ) {
                return true;
            }
            return regexp.test(value);
        }
    };
})();

在HTML中,无需进行任何更改:

<input type="text" ng-model="..." ng-required="requireTel"
    ng-pattern="phoneNumberPattern" />

实际上,这会诱使angular调用我们的 test()方法,而不是RegExp.test()考虑了这required一点的。


2
我很想知道函数周围以及函数之后的圆括号。没有他们
它就行不通

5
他们直接调用函数,有效地将其返回值放置到变量中。为了避免用特定组件的实现细节污染外部范围(例如,查看模块模式),这在Javascript中非常常见。
Nikos Paraskevopoulos 2014年

6
基于JS的“鸭嘴型”在AngularJS上发挥作用的肮脏解决方案是我今天看到的最棒的代码。真的很聪明的解决方案!
Florian Loch 2014年

感谢您提供的出色代码,但仍然不是很清楚:1)根据docs.angularjs.org/api/ng/directive/input,“如果表达式的计算结果为RegExp对象,则直接使用该表达式。如果表达式的计算结果为到字符串,然后将其转换为RegExp”,但是我想phoneNumberPattern是返回时的对象?这应该是Regxp Obj吗?2)在测试中的function(value){}中,参数“ value”从何而来?感谢任何答复!
user2499325

1
1)Angular通过检查表达式是否评估为RegExp子句是否具有test方法来实现。这就是为什么我们给它一个具有自己的自定义对象的原因,它test()本质上模拟了本机JS RegExp。2)value当执行实际的有效性检查时,Angular当然会传递。
Nikos Paraskevopoulos,2015年

25

从Nikos的出色答案中不脱颖而出,也许您可​​以更简单地做到这一点:

<form name="telForm">
  <input name="cb" type='checkbox' data-ng-modal='requireTel'>
  <input name="tel" type="text" ng-model="..." ng-if='requireTel' ng-pattern="phoneNumberPattern" required/>
  <button type="submit" ng-disabled="telForm.$invalid || telForm.$pristine">Submit</button>
</form>

注意第二个输入:我们可以使用anng-if来控制表单的呈现和验证。如果requireTel未设置变量,则第二个输入将不仅被隐藏,而且根本不会呈现,因此表单将通过验证,并且按钮将变为启用状态,您将获得所需的内容。


1
好处是,这很简单。不利的一面是,如果ng-if表达式随后为假,则当ng-if表达式为false时删除的所有输入都将删除其中的任何文本。不过,为简单起见,+ 1。
布拉德

我想补充一下,如果您走这条路线,请确保您了解ng-if中的所有内容(例如,如果将其放在div上)现在将具有其自己的作用域。
布拉德

5

使用模式:

 ng-pattern="/^\d{0,9}(\.\d{1,9})?$/"

使用的参考文件:

 '<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.js"></script>'

输入示例:

 <input type="number" require ng-pattern="/^\d{0,9}(\.\d{1,9})?$/"><input type="submit">


2

前几天我碰到了这个。

我所做的事情似乎比上面的要容易,它是在作用域上的变量上设置模式,并在视图的ng-pattern中引用它。

当“复选框未选中”时,我只需在onChanged回调中将正则表达式的值设置为/.*/(如果未选中)。ng-pattern会发生变化,并说“好的,您的值还可以”。表格现在有效。我还将从该字段中删除错误的数据,以免您坐在那里没有明显的错误电话。

我遇到了ng-required的其他问题,并做了同样的事情。像魅力一样工作。


0

如果ngModel $ viewValue与通过评估属性值中给出的Angular表达式找到的RegExp不匹配,则设置模式验证错误密钥。如果表达式的计算结果为RegExp对象,则可以直接使用它。如果表达式的计算结果为字符串,则将其用^和$字符包装后将转换为RegExp。

似乎该问题上投票最多的答案应该更新,因为当我尝试它时,它不适用test功能且验证不起作用。

Angular文档的示例对我有用

修改内置验证器

html

<form name="form" class="css-form" novalidate>
  <div>
   Overwritten Email:
   <input type="email" ng-model="myEmail" overwrite-email name="overwrittenEmail" />
   <span ng-show="form.overwrittenEmail.$error.email">This email format is invalid!</span><br>
   Model: {{myEmail}}
  </div>
</form>

js

var app = angular.module('form-example-modify-validators', []);

app.directive('overwriteEmail', function() {
    var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+/=?^_`{|}~.-]+@example\.com$/i;

    return {
        require: 'ngModel',
        restrict: '',
        link: function(scope, elm, attrs, ctrl) {
            // only apply the validator if ngModel is present and Angular has added the email validator
            if (ctrl && ctrl.$validators.email) {

                // this will overwrite the default Angular email validator
                ctrl.$validators.email = function(modelValue) {
                    return ctrl.$isEmpty(modelValue) || EMAIL_REGEXP.test(modelValue);
                };
             }
         }
     };
 });

柱塞


-1

您可以使用网站https://regex101.com/为某些国家/地区建立自己的特定模式:

例如,波兰:

-pattern = xxxxxxxxx OR xxx-xxx-xxx OR xxx xxx xxx 
-regexp ="^\d{9}|^\d{3}-\d{3}-\d{3}|^\d{3}\s\d{3}\s\d{3}"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.