【问题标题】:Reactive Form Validity based on IP Addresses RegEx基于 IP 地址 RegEx 的反应式表单有效性
【发布时间】:2020-02-18 22:12:19
【问题描述】:

更新:我发现使用简单的正则表达式(例如/^[0-9]+$/)可以重现这种行为。它也可以使用自定义验证器功能重现,例如

export function textareaPattern(pattern: RegExp): ValidatorFn {
    return (control: AbstractControl): {[key: string]: any} | null => {
        const values = control.value.split('\n');
        let mismatch = false;
        values.forEach(val => {
            mismatch = !pattern.test(val);
            if(mismatch) {
                return {textareaPattern: {value: control.value}}
            }
        });
        return null;
    }
}

原帖:我有一个正则表达式,用于验证用户是否在文本区域中输入了多个有效的 IP 地址(每行一个)。

/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3 }(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(/([0-9]|[1 -2][0-9]|3[0-2]))?$\n?/gim

正则表达式运行良好,但一旦同时存在有效条目和无效条目就会变得奇怪。

如果我输入所有有效值,则表单控件是有效的,正如预期的那样。示例:

10.1.121.2
10.2.121.3
10.3.121.4

如果我输入了所有无效值,则表单控件如预期的那样无效。示例:

butter
potato
123

如果我输入了有效值和无效值的组合,表单控件会在有效和无效之间交替,具体取决于条目的长度。如果条目的长度是偶数,它是无效的,奇数是有效的。多么奇怪。

长度:12,无效

10.1.121.1
f

长度:13,有效

10.1.121.1
fo

我认为问题出在 RegEx 上,但我承认我对破译如此庞大的 RegEx 感到很不自在。

RegEx 应该匹配:

192.168.1.1
255.203.232.1
1.0.12.1

RegEx 不应匹配:

256.1.12.1
1934.1.22.3
201.foobar.201.1

最小的、可重现的示例(已更新解决方案)https://stackblitz.com/edit/angular-v4f35a?file=src%2Fapp%2Fapp.component.ts

【问题讨论】:

  • 质量双关语非常受欢迎。我已经尝试了 here 的正则表达式,它似乎工作正常。我的猜测是用于输出真假的脚本存在一些问题。也许你可以再检查一次?
  • 此外,如果您在两个有效 IP 之间夹入一个无效输入,则输出每隔第三个字符而不是每个备用字符为假。不确定这是否是一个好的提示,但值得研究。
  • 感谢@RoboMop 的反馈 - 我没有注意到每三个字符的位,但我可以复制。我发现正则表达式在 Regexr 中也按预期工作,这让我认为问题可能出在 Angular 的表单而不是 RegEx 上——并不是说我对此很满意。至于输出真/假的脚本 - 这只是表单有效状态的反映,这完全取决于文本区域的内容是否与正则表达式匹配。

标签: regex angular angular-reactive-forms


【解决方案1】:

所以这归结为两个问题。

第一个问题是 RegExes 的 global 标志导致 JS 引擎跟踪 lastIndex 属性,当再次调用 myRegex.test() 时,下一次搜索将从该属性开始。由于 regex 对象在整个验证过程中都是相同的,因此 lastIndex 会在您键入时更新和引用,并且表单会重新验证。

第二个问题是如果没有global,只要一行正确,表单就会被认为是有效的。所以我的输入可能是

192.168.foobar
192.168.1.1
hello world!

由于第 2 行,表格有效。

我的解决方案

我已经为 textareas 实现了一个自定义验证器。它接受我的正则表达式(无g 标志)并在\n 上拆分文本区域的内容。它立即假定没有不匹配,然后对于每一行,检查该行是否与 RegEx 匹配。如果不是,则它不匹配并返回一个包含 textarea 内容的对象:

import {AbstractControl, ValidatorFn} from '@angular/forms';

export function multilinePattern(pattern: RegExp): ValidatorFn {
  return (control: AbstractControl): {[key: string]: any} | null => {
    const values = control.value.split('\n');
    if (values.length === 1 && values[0] === '') {
      return null;
    }
    let mismatch = false;
    values.forEach((val: string) => {
      if (!pattern.test(val)) {
        mismatch = true;
      }
    });
    return mismatch ? {multilinePattern: {value: control.value}} : null;
  };
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-11
    • 2016-12-01
    • 1970-01-01
    • 2021-10-26
    • 1970-01-01
    • 2019-08-04
    • 2020-10-28
    相关资源
    最近更新 更多