jjzjj

javascript - 当浏览器自动填写表单字段时,$parsers\$formatters 函数不会触发

coder 2024-07-25 原文

我的应用程序中有一个特定的自定义验证指令(下面附有代码)。 问题是,当需要一个或多个表单字段时,chrome 会自动填充它们,这些字段将保持无效,直到用户手动更改它们。 我怀疑发生这种情况是因为 chrome 在 angular even bootstraps 之前填充了字段。

有办法解决这个问题吗?

代码:

app.directive('myValidate', function($timeout, $filter) {
    return {
        require: 'ngModel',
        link: function(scope, elm, attrs, ctrl) {
              var validator = function(viewValue){
                var viewValueStr = viewValue + '';
                scope.valid = true;
                scope.fieldName = attrs.name;
                var nameStr = attrs.name + '';
                if(!attrs.displayName || attrs.displayName.length == 0){
                  // var nameObj = nameStr.split('_');
                  // for(var i = 0; i < nameObj.length; ++i){
                  //   nameObj[i] = nameObj[i].substr(0, 1).toUpperCase() + nameObj[i].slice(1);
                  // }
                  // var nameStrParsed = nameObj.join(' ');//olde code, working on name, not Hebrew comaptible
                  var nameStrParsed = attrs.placeholder + '';
                }
                else{//data-display-name attribute, the error display is different than the placeholder value
                  var nameStrParsed = attrs.displayName;
                }

                scope.fieldErrorDisplay = Boolean(nameStrParsed) ? nameStrParsed : $filter('translate')('THISFIELD');
                var valueRequired = scope.$eval(attrs.valueRequired);
                if(valueRequired && viewValueStr.length == 0 && !attrs.minLength){
                    scope.valid = false;  
                    scope.requirementSpec[nameStr] = [{
                      'msg' : scope.fieldErrorDisplay + ' ' + $filter('translate')('ISREQUIRED'),
                      'class' : undefined
                    }];
                  }
                  else{
                        // scope.fieldErrorDisplayObj[nameStr] = scope.fieldErrorDisplay + ' must meet the following requirements: ';
                        scope.requirementSpec[nameStr] = [];
                        if(attrs.minLength){
                          var itemValidity = viewValue.length >= attrs.minLength;
                          scope.valid = !itemValidity ? false : scope.valid;
                          var item = {
                            'msg' : $filter('translate')('MINLENGTH', {PARAM: attrs.minLength + ''}),
                            'class' : itemValidity ? 'valid' : undefined
                          };
                          scope.requirementSpec[nameStr].push(item);
                        }
                        else if(attrs.valueRequired){
                          var itemValidity = viewValue &&  viewValueStr && viewValueStr.length >= 1;
                          scope.valid = !itemValidity ? false : scope.valid;
                          var item = {
                            'msg' : $filter('translate')('FIELDREQUIRED'),
                            'class' : itemValidity ? 'valid' : undefined
                          };
                          scope.requirementSpec[nameStr].push(item);
                        }
                        if(attrs.maxLength){
                          var itemValidity = viewValue.length <= attrs.maxLength;
                          scope.valid = !itemValidity ? false : scope.valid;
                          var item = {
                            'msg' :  $filter('translate')('MAXLENGTH', {PARAM: attrs.maxLength + ''}),
                            'class' : itemValidity ? 'valid' : undefined
                          };
                          scope.requirementSpec[nameStr].push(item);
                        }
                        if(attrs.minLetters){
                          var itemValidity = (viewValue && /[A-z]/.test(viewValue));
                          scope.valid = !itemValidity ? false : scope.valid;
                          var item = {
                            'msg' :  $filter('translate')('MINLETTERS', {PARAM: attrs.minLetters + ''}),
                            'class' : itemValidity ? 'valid' : undefined
                          };
                          scope.requirementSpec[nameStr].push(item);
                        }
                        if(attrs.minNumbers){
                          var itemValidity = (viewValue && /\d/.test(viewValue));
                          scope.valid = !itemValidity ? false : scope.valid;
                          var item = {
                            'msg' : $filter('translate')('MINNUMBERS', {PARAM: attrs.minNumbers + ''}),
                            'class' : itemValidity ? 'valid' : undefined
                          };
                          scope.requirementSpec[nameStr].push(item);
                        }
                        if(attrs.validUrl){
                          // if(viewValue.indexOf('http') == -1){
                          //   viewValue = 'http://' + viewValue;
                          //   ctrl.$setViewValue(viewValue);
                          // }
                          // else if(viewValue.indexOf('http') != 0){
                          //   var httpIndex = viewValue.indexOf('http');w
                          //   viewValue = viewValue.substr(httpIndex);
                          //   ctrl.$setViewValue(viewValue);
                          // }
                          // var urlPattern = new RegExp("(http|https)://[\w-]+(\.[\w-]+)+([\w.,@?^=%&amp;:/~+#-]*[\w@?^=%&amp;/~+#-])?");
                           var urlPattern = new RegExp(/^(https?):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i);
                           //(http|https):\/\/([a-zA-Z0-9]+\.)?[a-zA-Z0-9][a-zA-Z0-9-]+\.[a-zA-Z]{2,6}?(.+){0, 100}$/i)
                          var itemValidity = !viewValue || viewValue.length == 0 || urlPattern.test(viewValue);
                          scope.valid = !itemValidity ? false : scope.valid;
                          // console.log(itemValidity);
                          var item = {
                            'msg' : $filter('translate')('VALIDURL'),
                            'class' : itemValidity ? 'valid' : undefined
                          };
                          scope.requirementSpec[nameStr].push(item);

                        }
                  }

                  if(scope.valid) {
                      ctrl.$setValidity(nameStr, true);
                      elm.removeClass('ng-required-invalid').removeClass('validatorError').removeClass('ng-invalid').addClass('ng-valid');
                      return viewValue;
                  } 
                  else {
                      ctrl.$setValidity(nameStr, false);                    
                      return undefined;
                  }
              }
              if(!scope.requirementSpec){
                scope.requirementSpec = {};
              }
              if(Boolean(attrs.valueRequired) || Boolean(attrs.minLength)){
                  ctrl.$setValidity(attrs.name, false);
                  // elm.removeClass('ng-valid').addClass('ng-invalid');
              }

            ctrl.$parsers.unshift(function(viewValue) {
              return validator(viewValue);
            });
            ctrl.$formatters.unshift(function(viewValue) {
              if(viewValue && viewValue != "" && viewValue.length > 0)
                return validator(viewValue);
            });
        }
    };
})

最佳答案

将以下代码添加到我的自定义验证指令的底部:

    scope.$on('triggerValidator', function(e, val){
      var viewValue = typeof $ === 'function' ? $('[name="' + attrs.name + '"]').val() : document.getElementsByName(attrs.name)[0].value;
      if(viewValue && viewValue.length > 0){
        try{
          ctrl.$setViewValue(viewValue);
          validator(viewValue);  
        }
        catch(SUPPRESS){}
      }
    });

以及我的 Controller 底部的以下内容:

   $timeout(function(){
        $rootScope.$broadcast('triggerValidator');
    }, 500)

请注意,在使用 jQuery 时,200 毫秒的超时时间就足够了,而在使用原生 JS 选择器时,我不得不将超时时间增加到 500 毫秒。

try-catch block 用于捕获 Angular 在尝试设置包含字符“@”的 View 值时抛出的奇怪解析器异常,但工作正常!

跟踪 Angular 存储库中的官方问题也很好: https://github.com/angular/angular.js/issues/1460

关于javascript - 当浏览器自动填写表单字段时,$parsers\$formatters 函数不会触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20492046/

有关javascript - 当浏览器自动填写表单字段时,$parsers\$formatters 函数不会触发的更多相关文章

  1. ruby - Highline 询问方法不会使用同一行 - 2

    设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案

  2. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

  3. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  4. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  5. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  6. ruby - 在 Ruby 中用键盘诅咒数组浏览 - 2

    我正在尝试在Ruby中制作一个cli应用程序,它接受一个给定的数组,然后将其显示为一个列表,我可以使用箭头键浏览它。我觉得我已经在Ruby中看到一个库已经这样做了,但我记不起它的名字了。我正在尝试对soundcloud2000中的代码进行逆向工程做类似的事情,但他的代码与SoundcloudAPI的使用紧密耦合。我知道cursesgem,我正在考虑更抽象的东西。广告有没有人见过可以做到这一点的库或一些概念证明的Ruby代码可以做到这一点? 最佳答案 我不知道这是否是您正在寻找的,但也许您可以使用我的想法。由于我没有关于您要完成的工作

  7. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  8. ruby-on-rails - 在 Rails 和 ActiveRecord 中查询时忽略某些字段 - 2

    我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr

  9. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  10. ruby-on-rails - 浏览 Ruby 源代码 - 2

    我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru

随机推荐