Вы должны получить ссылку родительского элемента ngModel
и дочернего элемента ngModel
в дочернем компоненте, а затем объединить валидаторы. К сожалению, поскольку вы используете NG_VALUE_ACCESSOR
, вы должны использовать Injector
, чтобы получить родительскую модель:
рабочий пример # 1
export class CustomInputComponent implements ControlValueAccessor {
@ViewChild(NgModel, { static: false }) ngModel: NgModel;
constructor(private _renderer: Renderer2, readonly injector: Injector) {}
ngAfterViewInit(): void {
const parentModel = this.injector.get(NgModel);
this.ngModel.control.setValidators([
this.ngModel.control.validator,
parentModel.validator
]);
this.ngModel.control.updateValueAndValidity();
}
}
Если у вас есть асинхронные валидаторы, вы должны повторить ту же процедуру для этих
Если вы не хотите использовать Injector
, существует другой способ заставить ваш компонент использовать NG_VALUE_ACCESSOR
, установив его в конструкторе вместо декоратора. К сожалению, setTimeout
тогда необходим в ngAfterViewInit
, потому что эта ловушка является дочерней, а не родительской (в отличие от ngOnInit
), и валидатор еще не будет установлен правильно:
рабочий пример # 2
@Component({
selector: 'app-custom-input',
templateUrl: './custom-input.component.html',
styleUrls: ['./custom-input.component.css']
})
export class CustomInputComponent implements ControlValueAccessor {
@ViewChild('inputElement', {static: false}) private _inputElement: ElementRef;
get inputElement(): ElementRef {
return this._inputElement;
}
@ViewChild(NgModel, { static: false }) ngModel: NgModel;
constructor(private _renderer: Renderer2, @Self() readonly parentModel: NgModel) {
this.parentModel.valueAccessor = this;
}
ngAfterViewInit(): void {
setTimeout(() => {
this.ngModel.control.setValidators([
this.ngModel.control.validator,
this.parentModel.control.validator
]);
this.ngModel.control.updateValueAndValidity();
})
}
}