如何重新验证具有多个相关字段的表单?(How to revalidate a form with multiple dependent fields?)

编程入门 行业动态 更新时间:2024-10-17 09:45:16
如何重新验证具有多个相关字段的表单?(How to revalidate a form with multiple dependent fields?)

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

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

指示:

(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表单(摘录,仅显示9个字段中的2个):

... <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> ...

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

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

带有范围的Angular指令。$ watch强制验证其他字段

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

但提供的示例有所不同:它只是关于密码和密码重复字段,其中只有一个字段具有分配的验证指令。 所以它与我的情况有所不同。

我试图在我的上面的代码中添加这个:

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

但是这会导致无限循环(为什么ngModel经常在没有任何进一步操作的情况下进行更改,除了验证应该始终导致相同?)。

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?).

最满意答案

这是我最终解决的问题。 看起来有点黑了我,但它的作品。

(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; } } } } })();

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; } } } } })();

更多推荐

本文发布于:2023-07-04 17:07:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1026952.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:多个   字段   表单   revalidate   fields

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!