Как различить несколько Validators.pattern
У меня есть вход, где пользователь должен ввести долготу. Я хочу иметь возможность отображать различные сообщения об ошибках, когда пользователь вводит NaN
или же Not-Precise-Enough
значение. я использую FormControl.hasError('ValidatorsName')
чтобы получить ошибки с проверкой, но кажется, что я не могу дифференцировать эти шаблоны.
Шаблон:
<mat-form-field class="form-field">
<input matInput placeholder="Logitude" [formControl]="longitude">
<mat-error *ngIf="longitude.hasError('pattern')">
Longitude must be <strong>a number</strong>
</mat-error>
<!-- I want to be able to check patter2 for example -->
<mat-error *ngIf="longitude.hasError('pattern')">
Longitude must have <strong>a minimum of 5 decimal numbers</strong>
</mat-error>
</mat-form-field>
И мой угловой код:
this.longitude = new FormControl(this.attraction.longitude, [
// is valid number
Validators.pattern(new RegExp('(\d{1,3})([.|,]{,1})(\d+))','gi')),
// is precise enough
Validators.pattern(new RegExp('(\-{0,1})(\d{1,3})([.|,]{1})(\d{5,13})','i'))
]);
Есть ли способ дать этим шаблонам идентификатор? Я буду признателен за любую помощь.
4 ответа
К сожалению, невозможно дать Validators собственный идентификатор.
ОБНОВЛЕНИЕ 17.02.2018 21:00
Как отметил в комментариях Давид Збински, что несколько ошибок с одной и той же ошибкой (например, 'pattern') получают переопределение, я обновил свой ответ.
Создайте пользовательский валидатор, которому передают регулярное выражение и предопределенную ошибку в качестве аргумента:
regexValidator(regex: RegExp, error: ValidationErrors): ValidatorFn {
return (control: AbstractControl): {[key: string]: any} => {
if (!control.value) {
return null;
}
const valid = regex.test(control.value);
return valid ? null : error;
};
}
и используйте это так:
this.longitude = new FormControl('', [
this.regexValidator(new RegExp('^[0-9]+$'), {'number': ''}),
this.regexValidator(new RegExp('^.{5,}$'), {'precision': ''})
]);
<mat-form-field class="form-field">
<input matInput placeholder="Logitude" [formControl]="longitude">
<mat-error *ngIf="longitude.hasError('number')">
Longitude must be <strong>a number</strong>
</mat-error>
<!-- I want to be able to check patter2 for example -->
<mat-error *ngIf="longitude.hasError('precision')">
Longitude must have <strong>a minimum of 5 decimal numbers</strong>
</mat-error>
</mat-form-field>
Я также обновил демонстрацию stackblitz: https://stackblitz.com/edit/angular-dvwcj3?file=app%2Fhello.component.ts
СТАРЫЙ ОТВЕТ:
Но PatternValidators
возвращаются уникальные ValidatonErrorObjects
,
Когда вы проверяете исходный код из валидатора шаблонов в официальном репозитории угловых операций, вы видите, что они всегда возвращают регулярное выражение внутри объекта ошибки.
return (control: AbstractControl): ValidationErrors | null => { if (isEmptyInputValue(control.value)) { return null; // don't validate empty values to allow optional controls } const value: string = control.value; return regex.test(value) ? null : {'pattern': {'requiredPattern': regexStr, 'actualValue': value}}; };
Имея это в виду, вы можете легко создать два метода получения внутри component.ts
файл. И они отличаются между двумя регулярными выражениями. В этом примере они просто проверяют, соответствует ли уникальная подстрока регулярному выражению. Наверняка они другие способы справиться с этим.
get numberError() {
if (this.longitude && this.longitude.hasError('pattern')) {
return this.longitude.getError('pattern').requiredPattern.indexOf('(\d+)') !== -1
}
return false;
}
get preciseError() {
if (this.longitude && this.longitude.hasError('pattern')) {
return this.longitude.getError('pattern').requiredPattern.indexOf('(\-{0,1})') !== -1
}
return false;
}
Вы можете создать вспомогательную функцию, которая может изменить имя ошибки валидатора:
function renameError(validator: ValidatorFn, name: string): ValidatorFn {
return (control: FormControl): ValidationErrors | null => {
const result = validator(control);
if (result) {
const keys = Object.keys(result);
if (keys.length === 1) {
result[name] = result[keys[0]];
delete result[keys[0]];
} else if (keys.length > 1) {
// Just in case validator for some reason returns multiple errors
result[name] = {valid: false};
}
}
return result;
};
}
и используйте его так:
this.longitude = new FormControl(this.attraction.longitude, [
renameError(
Validators.pattern(new RegExp('(\d{1,3})([.|,]{,1})(\d+))','gi')),
'notANumber'
),
renameError(
Validators.pattern(new RegExp('(\-{0,1})(\d{1,3})([.|,]{1})(\d{5,13})','i')),
'notPrecise'
)
]);
<mat-form-field class="form-field">
<input matInput placeholder="Logitude" [formControl]="longitude">
<mat-error *ngIf="longitude.hasError('notANumber')">
Longitude must be <strong>a number</strong>
</mat-error>
<mat-error *ngIf="longitude.hasError('notPrecise')">
Longitude must have <strong>a minimum of 5 decimal numbers</strong>
</mat-error>
</mat-form-field>
Решение SplitterAlex не сработало для меня, пока я не изменил значение объекта ошибки с
''
к
true
this.longitude = new FormControl('', [
this.regexValidator(new RegExp('^[0-9]+$'), {'number': true}),
this.regexValidator(new RegExp('^.{5,}$'), {'precision': true})
]);
Мне нужно было настроить ответ @SoMuchSpace для angular 16:
renameError(validator: ValidatorFn, name: string): ValidationErrors | null {
return (control: FormControl): ValidationErrors | null => {
const result = validator(control);
if (result) {
const keys = Object.keys(result);
if (keys.length === 1) {
result[name] = result[keys[0]];
delete result[keys[0]];
} else if (keys.length > 1) {
// Just in case validator for some reason returns multiple errors
result[name] = {valid: false};
}
}
return result;
};
}
this.longitude = new FormControl(this.attraction.longitude, [
renameError(
Validators.pattern(new RegExp('(\d{1,3})([.|,]{,1})(\d+))','gi')),
'notANumber'
) as ValidatorFn,
renameError(
Validators.pattern(new RegExp('(\-{0,1})(\d{1,3})([.|,]{1})(\d{5,13})','i')),
'notPrecise'
) as ValidatorFn
]);
Без этой настройки я получил эту ошибку:
error TS2322: Type '(control: FormControl) => ValidationErrors | null' is not assignable to type 'ValidatorFn'