Я хотел бы динамически добавлять валидаторы в свой FormControl с помощью настраиваемой директивы.
@Directive({
selector: "[idNumber]",
})
export class IdNumberDirective implements OnInit {
constructor(private formControl: FormControl) { }
ngOnInit() {
this.addValidators(this.formControl);
}
addValidators(formControl: FormControl) {
formControl.setValidators(Validators.compose(
[Validators.required,
Validators.minLength(3),
Validators.maxLength(8)
]
));
}
<mat-form-field>
<mat-label>{{label}}</mat-label>
<input matInput
[formControl] = "idNumberFormControl"
[placeholder] = "placeholder"
</mat-form-field>
Мне не нужно ссылаться на nativeElement (через ElementRef).
Я хотел бы сослаться на formControl ...
... и используйте его как таковое:
// HTML with my custom directive 'idNumber' ////////
<custom-input-string
idNumber
[name] = "'idNumber'"
[label] = "Id Number"
[placeholder] = "">
</custom-input-string>
// TS ////////
@ViewChild(CustomInputStringComponent) child: CustomInputStringComponent;
ngAfterViewInit() {
setTimeout(() => {
this.child.insertIntoForm(this.signupForm);
}, 0);
}
Любые идеи?
Спасибо всем.





Если вы используете NgControl и DI-инъекцию конструктора, у нас может быть директива, применимая к элементам управления формы из реактивных форм в формах formControlName или шаблонов:
Директива:
import { Directive } from "@angular/core";
import { NgControl } from "@angular/forms";
@Directive({
selector: '[my-directive]'
})
export class MyDirective {
constructor(private el: ElementRef, private control : NgControl) { }
}
Мы можем получить ссылку на экземпляр элемента управления формой через DI с помощью NgControl. Вы можете получить доступ к методам управления формой, используя этот экземпляр
не могли бы вы обновить свой ответ, добавив еще код ?. Также - в чем смысл «частного el: ElementRef» в вашем предложении?
Вот пример использования директивы для добавления валидаторов к вашему элементу управления формой.
Обратите внимание, что использование этого приведет к потере всех ваших предыдущих валидаторов.
constructor(
// Get the control directive
private control: NgControl
) { }
ngOnInit() {
const abstractControl = this.control.control;
abstractControl && abstractControl.setValidators([Validators.required]);
}
привет, разве onEvent не запускается каждый раз при изменении значения FormControl? Я имею в виду, разве это событие не срабатывает каждый раз, когда пользователь нажимает любую клавишу, находясь в фокусе FormControl? Нет ли способа проверить и установить эти валидаторы в методе OnInit директивы? Спасибо.
Да, он запускается при каждом нажатии клавиши, но условие в функции предотвращает установку валидаторов несколько раз. Это должно быть сделано таким образом, потому что конструктор не знает об элементе управления. Вы также можете использовать ngOnInit (), как в этот stackblitz, который я обновил в своем ответе (потому что это действительно более понятно!)
Потрясающие! Именно то, что я искал! Спасибо!
Этот ответ отлично работает, но я думаю, что основной аспект (использование NgControl вместо FormControl OP) слишком ценен, чтобы оставаться во внешней ссылке (Stackblitz). Я предлагаю поместить эту часть прямо в ответ, как и @Suresh в своем ответе.
//TestAnythingsComponent.ts
import { Component, OnInit } from '@angular/core';
import { FormControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
import { IdNumberDirective } from '../directives/IdNumberDirective.directive';
@Component({
selector: 'app-test-anythings',
templateUrl: './test-anythings.component.html',
styleUrls: ['./test-anythings.component.css'],
providers:[IdNumberDirective]
})
export class TestAnythingsComponent implements OnInit {
testForm: FormGroup;
constructor(fb: FormBuilder, IdNumberDirective : IdNumberDirective) {
this.testForm = fb.group({
idNumberFormControl : new FormControl(null,
Validators.compose([
Validators.required,
Validators.minLength(3),
Validators.maxLength(8),
IdNumberDirective.customValidator()
])
),
})
}
}
//IdNumberDirective.ts
import { Directive, OnInit } from '@angular/core';
import { Validators, ValidatorFn, AbstractControl, ValidationErrors } from '@angular/forms';
@Directive({
selector: '[idNumber]'
})
export class IdNumberDirective implements OnInit {
constructor() {
}
ngOnInit() {
}
customValidator(): ValidatorFn {
Validators.nullValidator
return (control: AbstractControl): ValidationErrors | null => {
//any condition to check control value
if (control.value != "Sachin") {
//return key value pair of errors
return { "customError": { inValid: true, errMsg: 'Invalid Value' } };
}
return null;
}
}
}
//test-anythings.component.html
<form [formGroup] = "testForm">
<input idNumber formControlName = "idNumberFormControl" />
<div *ngIf = "testForm.get('idNumberFormControl').invalid && testForm.get('idNumberFormControl').errors.customError.inValid"
style = "color:red">
{{testForm.get('idNumberFormControl').errors.customError.errMsg}}
</div>
<button type = "submit">submit</button>
</form>
Уважаемый Сачин, не могли бы вы добавить комментарий к вашему коду, чтобы облегчить понимание вашего подхода?
Привет, Артем, посмотри на мое решение выше, пожалуйста, введите «Sachin», чтобы сообщение об ошибке исчезло, я старался изо всех сил, я новичок в angular. Спасибо.
Привет, @Suresh, спасибо за предложение, но мне нужно более подробное объяснение. Смогу ли я это сделать? this.addValidators (this.control); Это сработает? PS: Я не использую и никогда не буду использовать «формы на основе шаблонов».