I have a component with a custom Form Control
. And in this component I need to get a list of validators from the parent component. I use Reactive forms everywhere, so I don't need to inject NG_VALIDATORS
, I don't need custom validators, I need exactly the parent component's validators.
Some examples:
export class ParentComponent {
public loginForm: FormGroup = this.fb.group({
email: new FormControl('', [Validators.required, Validators.email]),
password: new FormControl('', [
Validators.required,
Validators.minLength(6),
]),
});
}
<form [formGroup]="loginForm">
<child-component type="email" formControlName="email"></child-component>
<child-component type="password" formControlName="password"></child-component>
</form>
export class ChildComponent implements ControlValueAccessor, AfterViewInit {
valueControl = new FormControl('');
constructor( private injector: Injector ) { }
ngAfterViewInit() {
const ngControl = this.injector.get(NgControl);
// here I need something like this: const validators = ngControl.control?.validatorsList;
this.valueControl.setValidators(validators);
}
// some ControlValueAccessor interface
}
<mat-form-field>
<input
matInput
[type]=type
[formControl]="valueControl"
/>
</mat-form-field>
I see a couple of acceptable solutions:
export class ParentComponent {
emailValidators = [Validators.required, Validators.email];
public loginForm: FormGroup = this.fb.group({
email: new FormControl('', emailValidators),
password: new FormControl('', [
Validators.required,
Validators.minLength(6),
]),
});
}
<form [formGroup]="loginForm">
<child-component [validators]=emailValidators type="email" formControlName="email"></child-component>
</form>
export class ChildComponent implements ControlValueAccessor {
@Input() validators;
valueControl = new FormControl('');
constructor( private injector: Injector ) {
this.valueControl.setValidators(this.validators);
}
// some ControlValueAccessor interface
}
export class ChildComponent implements ControlValueAccessor, AfterViewInit {
valueControl = new FormControl('');
constructor( private injector: Injector ) { }
ngControl.control?.statusChanges.subscribe(() => {
// use ngControl.control?.errors
});
// some ControlValueAccessor interface
}
In connection with all the above I have a question:
Are there best practices to solve this issue? And also why does Angular AbstractControl
not provide such a function, but only has private variables like _rawValidators
?
The property validator
of an abstractControl is a FnValidator, so you can simply use
valueControl = new FormControl('');
ngControl = this.injector.get(NgControl);
ngAfterViewInit() {
this.valueControl.setValidators(this.ngControl?.control?.validator || null);
this.valueControl.updateValueAndValidity();
}
NOTE: I put as property of the component the ngControl. In this way you can check the property of it
NOTE related stackblitz:in the stackblitz it's necessary, when change "valueControl" call to the function this.onChange(value)
to give value to the control.