【问题标题】:Restricting Characters in Input Field to a Set of Characters将输入字段中的字符限制为一组字符
【发布时间】:2014-10-14 07:24:07
【问题描述】:

问题更新:如何防止使用 AngularJS(或 jQuery)将除 char 数组中指定的字符之外的所有字符输入到输入字段中?


老问题:

我的 AngularJS 应用程序中有一个简单的 <input type="text" /> 字段,我希望用户只能在该字段中输入以下字符:

0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~

我知道我可以将ng-pattern="allowed" 添加到&lt;input&gt;,然后将$scope.allowed 设置为某个正则表达式模式,如果输入任何无效字符,这将标记输入无效,但我也想防止受限字符全部输入到字段中。

所以我的问题由两个问题组成:

  1. 我使用什么正则表达式模式将字符集限制为我上面发布的字符集?
  2. 如何防止在字段中输入非法字符? (例如,如果您输入一个小写字母,那么它将不会出现在该字段的开头,同样,如果您尝试粘贴包含任何非法字符的文本,它们将立即被删除)

【问题讨论】:

  • 使用[0-9] 而不是0123456789。包含[...]+定义的字符类中的所有字符
  • @user3218114 看起来像$scope.allowed = /[0-9][*+,-./:;]+/;
  • 查看demo。所有属于正则表达式模式的特殊字符都应进行转义,例如[].*{}- 等。
  • 你必须把破折号(-)放在开头或结尾,否则JS会认为它是一个范围:/[-0-9*+,./:;]+/
  • @user3218114 测试您的演示链接,这绝对看起来像我想要的模式,现在我需要弄清楚如何根据该模式限制进入。谢谢!

标签: javascript regex html angularjs


【解决方案1】:

尝试使用 regExp 通过传递 $event 来过滤 ng-keypress 上不必要的字符。

#plnk会更清楚!

【讨论】:

  • 这行得通,只是我可以复制+粘贴大写字符来绕过它。我正在考虑在ng-change 上验证模型,然后通过用"" 替换它们来从模型中删除无效字符,但我不知道如何对不包含在正则表达式集中的每个字符进行字符串替换...
  • 据我了解,您不想传递大写字母,所以我想这就是 plnk 您想要的。
  • 不,我想删除所有不在 OP 列表中的字符。
  • @StickFigs,剪切和粘贴长期以来一直是模型绑定和验证的“棘手”问题。粘贴事件不是 AngularJS 自然监听的事件。调整 Alex 的答案以验证输入何时失去焦点。这并不理想,但可能与您在剪切粘贴后进行验证一样接近。
  • @AlexCross,对未来答案的建议。 Plunkers 很棒,但在您的答案中也包含重要的代码 sn-ps。这样可以提供更高质量的答案,并且不依赖于此 Plunker 或站点继续。最好的答案是 1) 解释,2) 代码 sn-ps,3) Plnker / Fiddle
【解决方案2】:

为了“限制输入某些字符”,我想到的是在输入上附加“keyup”、“change”、“paste”事件的事件处理程序,以及当它们被触发以“清除”它们的值时你的模式。我将逻辑实现为 jQuery 插件,但您可以将其调整为 angular、使用更好的命名或任何您想要的。

插件:

$.fn.restrictInputs = function(restrictPattern){
    var targets = $(this);

    // The characters inside this pattern are accepted
    // and everything else will be 'cleaned'
    // For example 'ABCdEfGhI5' become 'ABCEGI5'
    var pattern = restrictPattern || 
        /[^0-9A-Z !\\"#$%&'()*+,\-.\/:;<=>?@\[\]^_`{|}~]*/g; // default pattern

    var restrictHandler = function(){
        var val = $(this).val();
        var newVal = val.replace(pattern, '');

        // This condition is to prevent selection and keyboard navigation issues
        if (val !== newVal) {
            $(this).val(newVal);
        }
    };

    targets.on('keyup', restrictHandler);
    targets.on('paste', restrictHandler);
    targets.on('change', restrictHandler);
};

用法:

$('input').restrictInputs();

// Or ...

$('.my-special-inputs-decorated-with-this-class').restrictInputs();

这是JsFiddle Demo

注意:您可以尝试更改实现以接受带有禁止字符的字符串而不是正则表达式,并动态创建正则表达式。此外,您可能会发现其他适合触发“清理”的事件。

【讨论】:

  • hmmmm... 这肯定会起作用,但很可能会导致更新 Angular 模型出现问题。 JQuery 和 Angular 配合使用存在问题
  • @DaveA 我对 AngularJS 不是很熟悉,OP 要求 Angular 或 jQuery 解决方案,所以我选择了 jQuery。如果您认为此解决方案可以适应 Angular,请随时更新我的​​答案、提供建议或发布另一个答案 :)
  • Viktor,我同意你有一个很好的实现。它实际上可能与 Angular 一起使用。我会考虑的!
  • 维克多,看看我的 Plunker。我将你的正则表达式添加到 Alex 的,我想我已经证明了你的概念!plnkr.co/edit/PiW7yFotqTylDTY3d8Ae?p=preview
  • +1 有效。只有引用,您的正则表达式允许单引号和空格
【解决方案3】:

Angular 的方法是利用 Angular 的 ngModelController.$parsers 参见documentation:

$解析器

作为管道执行的函数数组,无论何时 控件从 DOM 中读取值。依次调用每个函数, 将值传递给下一个。使用最后一个返回值 填充模型。用于清理/转换值以及 验证。为了验证,解析器应该更新有效性 状态使用 $setValidity(),并返回 undefined 无效值。

这是一个使用这种方法的可重用指令的示例:

app.directive('inputRestrictor', [
  function() {
    return {
      restrict: 'A',
      require: 'ngModel',
      link: function(scope, element, attr, ngModelCtrl) {
        var pattern = /[^0-9A-Z !\\"#$%&'()*+,\-.\/:;<=>?@\[\]^_`{|}~]*/g;

        function fromUser(text) {
          if (!text)
            return text;

          var transformedInput = text.replace(pattern, '');
          if (transformedInput !== text) {
            ngModelCtrl.$setViewValue(transformedInput);
            ngModelCtrl.$render();
          }
          return transformedInput;
        }
        ngModelCtrl.$parsers.push(fromUser);
      }
    };
  }
]);

这是plnkr demo

*上述指令的正则表达式模式取自 Viktor Bahtev 的回答。

您显然也可以扩展此指令以获取输入参数。我会把它留给你的练习。

【讨论】:

  • 当你可以简单写的时候,真的有必要写这个怪异的字符类吗(如果你看一下ascii表):[ -`{-~]
  • 另一件事:你的模式可以匹配一个空字符串,因为你使用了* 量词。真的是你想要的吗? (请注意,使用这种模式,在遇到禁止字符之前,您将在字符串中的每个位置用空(无用)替换空。)
  • @CasimiretHippolyte 我认为您错过了我回答的重点。答案更多是关于如何使用推荐的 AngularJs 方法(即使用带有 $parsers 的指令)过滤输入文本,而不是实际的 RegEx 模式。我认为这很清楚,因为我清楚地表明我使用了已经接受的答案中的模式。只是一个建议,您为什么不使用您的超精益模式发布答案?
  • 哦,您只需要复制/粘贴已接受答案的模式!请原谅,我很抱歉。
  • @CasimiretHippolyte,我认为你错过了意义。 Beyers 正在使用 AngularJS 指令应用正则表达式(实际上就是这样)。在您使用 AngularJS 完成大量工作之前,这似乎并不重要,但是如果您避免使用 JQuery 并创建纯粹的 AngularJS 答案,性能会更好,应用程序也会更干净。我不认为这个答案值得投反对票,虽然 OP 对混合答案很满意,但我发现这很有用,值得一票。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-29
  • 1970-01-01
  • 2012-02-11
  • 1970-01-01
  • 1970-01-01
  • 2017-12-17
  • 1970-01-01
相关资源
最近更新 更多