Angular 2,数据验证和输入掩码的困难

6

我根据https://auth0.com/blog/angular-2-series-part-5-forms-and-custom-validation/中的说明实现了表单验证。

 <input class="form-control"
               type="text"
               name="phone"
               autocomplete="off"
               placeholder="(XXX)-XXX-XXXX"
               mask=""
               [disabled]="disabled"
               [(ngModel)]="candidate.phone"
               ngControl="phone"/>

抱歉,您需要提供要翻译的内容。
static phone(control: Control): ValidationResult {

    let URL_REGEXP = /^\(\d{3}\)-\d{3}-\d{4}$/i;

    if (control.value && (control.value.length <= 5 || !URL_REGEXP.test(control.value))) {

        return {"phone": true};
    }

    return null;
}

针对这个元素,我已经实现了输入掩码目录:http://pastebin.com/wRzHSsVy

以下问题会出现:当输入电话号码时,验证器会先起作用,然后是输入掩码目录。因此,验证器检查的数据和输入掩码目录格式化的数据不同。例如,验证器上的电话号码为(888)-888-88882,而掩码将该号码转换为以下格式(888)-888-8888,但验证器已经工作并指出了掩码激活前的错误。

2个回答

0

我有一个非常类似的问题,也与电话掩码/验证器有关。我的最初想法是在调用“this.control.valueAccessor.writeValue(...)”后以某种方式重新调用验证。

我的尝试是添加:

this.control.control.updateValueAndValidity(
{ 
  onlySelf: true, 
  emitEvent: false 
});

看起来这会再次触发表单验证,但提交给验证器的值仍然是不正确的(预掩码)值。

然而,我在我的输入中没有使用[(ngModel)],所以你可能需要使用类似于这篇帖子建议的的东西。


0

经过一些调研,我找到了一个解决方法。虽然感觉有点“肮脏”。

我的掩码类正在附加到(input)和(keyup.backspace)事件:

...
host: {
  '(input)': 'onInputChange($event.target.value)',
  '(keyup.backspace)': 'onInputChange($event.target.value, true)'
}
...

我不是这样做的,而是依附于(模糊)和(焦点)事件。

...
host: {
    '(blur)': 'onInputChange($event.target.value)',
    '(focus)': 'removeMask($event.target.value)'
}
...

当焦点在输入框上时,我会移除掉掩码,然后在失去焦点时再添加回来。这样可以确保验证器在值发生变化时获取到正确的值,而不会受到掩码的干扰。接着,我将FormControl更改为使用数字验证器,而不是电话验证器,因为被验证的值不会应用掩码。

电话掩码:

@Directive({
    selector: '[phoneMask]',
    host: {
        '(blur)': 'onInputChange($event.target.value)',
        '(focus)': 'removeMask($event.target.value)'
    }
})
export class PhoneMask {

    constructor(public control: NgControl) { }

    onInputChange(value) {
        // remove all mask characters (keep only numeric)
        var newVal = value.replace(/\D/g, ''); // non-digits

        // set the new value
        this.control.valueAccessor.writeValue(PhoneMask.applyMask(newVal));        
    }

    removeMask(value) {
        this.control.valueAccessor.writeValue(value.replace(/\D/g, ''));
    }

    static applyMask(value: string): string {
        if (value.length == 0) {
            value = '';
        } else if (value.length <= 3) {
            value = value.replace(/^(\d{0,3})/, '($1)');
        } else if (value.length <= 6) {
            value = value.replace(/^(\d{0,3})(\d{0,3})/, '($1) $2');
        } else {
            value = value.replace(/^(\d{0,3})(\d{0,3})(.*)/, '($1) $2-$3');
        }
        return value;
    }
}

数字验证器:

export function validateNumeric(control: FormControl) {
    let regex = /[0-9]+/;
    return !control.value || regex.test(control.value) ? null : { numeric: { valid: false } };
}

我曾经看到过类似的实现,但它与 (ngModelChange)(keydown.backspace) 相关联。backspace 用于处理掩码更改,以便在每次击键时 backspace 可以删除数字。这是它的链接:https://dev59.com/uFoU5IYBdhLWcg3wHEVp#37887432 - Machtyn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接