如何重新验证具有多个依赖字段的表单? [英] How to revalidate a form with multiple dependent fields?

查看:18
本文介绍了如何重新验证具有多个依赖字段的表单?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对 Angular 还很陌生.我有一个表单,用户需要将端口号分配给 9 个不同的端口输入字段(上下文:它是服务器环境配置的表单).验证要求是不能分配两次端口号,因此 9 个端口号中的每一个都必须是唯一的.

为此,我有一个名为srb-unique-port"的自定义验证指令,我将其分配给我的输入字段.

指令:

(函数(){'使用严格';有角的.module('账户').directive('srbUniquePort', [srbUniquePort]);函数 srbUniquePort() {返回 {限制:'A',要求:'ngModel',范围:真实,链接:函数(范围、元素、属性、ngModel){ngModel.$validators.srbUniquePort = 函数 (val) {if (val == null || val == undefined || val == "" || val==0) 返回真;var fieldName = attrs.name;var configuration = scope.$eval(attrs.srbUniquePort);var portFieldsToCheck = ["myRestServicePort","myRestServicePortSSL","alfrescoPortHttp","alfrescoPortHttps","alfrescoPortTomcatShutdown","alfrescoPortAJP","alfrescoPortMySql","露天PortJOD",露天PortVti"];for (var i = 0; i < portFieldsToCheck.length; i++) {if (fieldName!=portFieldsToCheck[i] && configuration[portFieldsToCheck[i]] == val) {返回假;}}返回真;}}}}})();

HTML 表单(摘录,仅显示 9 个字段中的 2 个):

<代码> ...<md-输入-容器><label for="company" translate>COMPANY.CONFIGURATION.DBLIB_WEB_SRVC_PORT</label><input ng-model="vm.configuration.dblibWebSrvcPort" name="dblibWebSrvcPort" srb-unique-port="vm.configuration"><div ng-messages="configurationForm.dblibWebSrvcPort.$error"><div ng-message when="srbUniquePort"><span translate>COMPANY.CONFIGURATION.VALIDATION.PORT_NOT_UNIQUE</span>

</md-input-container><md-输入-容器><label for="company" translate>COMPANY.CONFIGURATION.DBLIB_WEB_SRVC_PORT_SSL</label><input ng-model="vm.configuration.dblibWebSrvcPortSLL" name="dblibWebSrvcPortSLL" srb-unique-port="vm.configuration"><div ng-messages="configurationForm.dblibWebSrvcPortSLL.$error"><div ng-message when="srbUniquePort"><span translate>COMPANY.CONFIGURATION.VALIDATION.PORT_NOT_UNIQUE</span>

</md-input-container>...

它基本上适用于我当前正在输入值的字段.但问题是,当我更改一个输入字段的值时,我还需要重新验证所有其他依赖字段.但我不确定最好的方法是什么,以免在这里陷入无限循环,因为所有字段都分配了srb-unique-port".

我已经查看了 StackOverflow 并发现了这个非常相似的问题:

带有scope.$watch 强制验证其他字段

使用这个plunker示例代码:http://plnkr.co/edit/YnxDDAUCS2K7KyXT1AXP?p=preview

但提供的示例有所不同:它仅涉及密码和密码重复字段,其中只有一个字段分配了验证指令.所以它与我的情况不同.

我尝试在上面的代码中添加:

scope.$watch(ngModel, function (newValue, oldValue) {ngModel.$validate();});

但这会导致无限循环(为什么 ngModel 经常在这里更改而没有任何进一步的操作,除了验证应该总是导致相同的结果?).

解决方案

这是我最终得到的解决方案.对我来说看起来有点黑,但它有效.

(函数(){'使用严格';有角的.module('账户').directive('srbUniquePort', [srbUniquePort]);函数 srbUniquePort() {返回 {限制:'A',要求:'ngModel',范围:真实,链接:函数(范围、元素、属性、ngModel){函数 hasAValue(field) {返回 !! 字段;}ngModel.$validators.srbUniquePort = 函数 (val) {var fieldName = attrs.name;var configuration = scope.$eval(attrs.srbUniquePort);var portFieldsToCheck = ["dblibWebSrvcPort","dblibWebSrvcPortSLL","myRestServicePort","myRestServicePortSSL","alfrescoPortHttp","alfrescoPortHttps","alfrescoPortTomcatShutdown","alfrescoPortAJP","alfrescoPortMySql","露天PortJOD",露天PortVti"];配置[字段名称] = val;if (scope.$parent.configuration == undefined) {scope.$parent.configuration = JSON.parse(JSON.stringify(configuration));}scope.$parent.configuration[fieldName] = val;//将每个端口字段相互比较,如果相等,//通过在validityMap 辅助变量中放入false"来记住它varvalidityMap = [];for (var i = 0; i < portFieldsToCheck.length; i++) {for (var j = 0; j 

I'm fairly new to Angular. I have a form where the user need to assign port numbers to 9 different port input fields (context: it's a form for a server environment configuration). The validation requirement is that no port number can be assigned twice, so each of the 9 port numbers needs to be unique.

For that, I have a custom validation directive called "srb-unique-port", which I assign to my input fields.

Directive:

(function () {
    'use strict';

    angular
        .module('account')
        .directive('srbUniquePort', [srbUniquePort]);

    function srbUniquePort() {
        return {
            restrict: 'A',
            require: 'ngModel',            
            scope: true,     
            link: function (scope, element, attrs, ngModel) {

                ngModel.$validators.srbUniquePort = function (val) {                    
                    if (val == null || val == undefined || val == "" || val==0) return true;
                    var fieldName = attrs.name;
                    var configuration = scope.$eval(attrs.srbUniquePort);                    

                    var portFieldsToCheck = [
                        "myRestServicePort",
                        "myRestServicePortSSL",
                        "alfrescoPortHttp",
                        "alfrescoPortHttps",
                        "alfrescoPortTomcatShutdown",
                        "alfrescoPortAJP",
                        "alfrescoPortMySql",
                        "alfrescoPortJOD",
                        "alfrescoPortVti"
                    ];                    
                    for (var i = 0; i < portFieldsToCheck.length; i++) {
                        if (fieldName!=portFieldsToCheck[i] && configuration[portFieldsToCheck[i]] == val) {
                          return false;
                        }
                    }                    
                    return true;
                }                             

            }
        }
    }
})();

HTML form (excerpt, just showing 2 of the 9 fields):

    ...
    <md-input-container>
        <label for="company" translate>COMPANY.CONFIGURATION.DBLIB_WEB_SRVC_PORT</label>
        <input ng-model="vm.configuration.dblibWebSrvcPort" name="dblibWebSrvcPort" srb-unique-port="vm.configuration">
        <div ng-messages="configurationForm.dblibWebSrvcPort.$error">
            <div ng-message when="srbUniquePort">
                <span translate>COMPANY.CONFIGURATION.VALIDATION.PORT_NOT_UNIQUE</span>
            </div>
        </div>
    </md-input-container>
    <md-input-container>
        <label for="company" translate>COMPANY.CONFIGURATION.DBLIB_WEB_SRVC_PORT_SSL</label>
        <input ng-model="vm.configuration.dblibWebSrvcPortSLL" name="dblibWebSrvcPortSLL" srb-unique-port="vm.configuration">
        <div ng-messages="configurationForm.dblibWebSrvcPortSLL.$error">
            <div ng-message when="srbUniquePort">
                <span translate>COMPANY.CONFIGURATION.VALIDATION.PORT_NOT_UNIQUE</span>
            </div>
        </div>
    </md-input-container>
    ...

It basically works for the field that I am current entering a value into. But the problem is that when I change the value of one input field, I need to re-validate all other depending fields as well. But I am not sure what the best way is in order to not run into an endless loop here, since all fields have the "srb-unique-port" assigned.

I already looked on StackOverflow and found this very similar question:

Angular directive with scope.$watch to force validation of other fields

with this plunker sample code: http://plnkr.co/edit/YnxDDAUCS2K7KyXT1AXP?p=preview

but the example provided there is different: it's only about a password and a password repeat field, where only one field has the validation directive assigned. So it differs from my case.

I tried to add this in my above code:

scope.$watch(ngModel, function (newValue, oldValue) {
    ngModel.$validate();
});

but this causes endless loops (why does the ngModel frequently change here without any further action other than a validation which should always result to the same?).

解决方案

This is the solution I ended up with. Looks a bit hacked to me, but it works.

(function () {
    'use strict';

    angular
        .module('account')
        .directive('srbUniquePort', [srbUniquePort]);

    function srbUniquePort() {
        return {
            restrict: 'A',
            require: 'ngModel',
            scope: true,
            link: function (scope, element, attrs, ngModel) {

                function hasAValue(field) {
                    return !!field;
                }

                ngModel.$validators.srbUniquePort = function (val) {

                    var fieldName = attrs.name;

                    var configuration = scope.$eval(attrs.srbUniquePort);
                    var portFieldsToCheck = [
                        "dblibWebSrvcPort",
                        "dblibWebSrvcPortSLL",
                        "myRestServicePort",
                        "myRestServicePortSSL",
                        "alfrescoPortHttp",
                        "alfrescoPortHttps",
                        "alfrescoPortTomcatShutdown",
                        "alfrescoPortAJP",
                        "alfrescoPortMySql",
                        "alfrescoPortJOD",
                        "alfrescoPortVti"
                    ];
                    configuration[fieldName] = val;

                    if (scope.$parent.configuration == undefined) {
                        scope.$parent.configuration = JSON.parse(JSON.stringify(configuration));
                    }
                    scope.$parent.configuration[fieldName] = val;

                    // compare each port field with each other and in case if equality, 
                    // remember it by putting a "false" into the validityMap helper variable
                    var validityMap = [];
                    for (var i = 0; i < portFieldsToCheck.length; i++) {
                        for (var j = 0; j < portFieldsToCheck.length; j++) {
                            if (portFieldsToCheck[i] != portFieldsToCheck[j]) {

                                var iFieldHasAValue = hasAValue(scope.$parent.configuration[portFieldsToCheck[i]]);
                                var jFieldHasAValue = hasAValue(scope.$parent.configuration[portFieldsToCheck[j]]);
                                var valHasAValue = hasAValue(val);

                                if (iFieldHasAValue && jFieldHasAValue
                                    && scope.$parent.configuration[portFieldsToCheck[i]] == scope.$parent.configuration[portFieldsToCheck[j]]
                                    ) {
                                    validityMap[portFieldsToCheck[i]] = false;
                                    validityMap[portFieldsToCheck[j]] = false;
                                }
                            }
                        }
                    }

                    // in the end, loop through all port fields and set
                    // the validity here manually
                    for (var i = 0; i < portFieldsToCheck.length; i++) {
                        var valid = validityMap[portFieldsToCheck[i]];
                        if (valid == undefined) valid = true;
                        ngModel.$$parentForm[portFieldsToCheck[i]].$setValidity("srbUniquePort", valid);
                    }

                    // ending with the standard validation for the current field
                    for (var i = 0; i < portFieldsToCheck.length; i++) {
                        if (fieldName != portFieldsToCheck[i] && configuration[portFieldsToCheck[i]] == val) {
                            return false;
                        }
                    }
                    return true;
                }

            }
        }
    }
})();

这篇关于如何重新验证具有多个依赖字段的表单?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆