If the child component should be always required, then you can implement the Validator
interface, and provide the NG_VALIDATORS token in the child component, to sync the invalid state with the parent form-group.
You can try the following to achieve that in this case:
@Component({
// ...
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => ChildComponent),
multi: true,
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => ChildComponent),
multi: true,
},
],
})
export class ChildComponent implements ControlValueAccessor, Validator {
innerCtrl: FormControl; // Use it to access the inner component value and invalid state.
onValidationChange: () => void;
validate(control: AbstractControl): ValidationErrors | null {
if (this.innerCtrl.invalid) {
return { invalid: true };
} else {
return null;
}
}
registerOnValidatorChange?(fn: () => void): void {
this.onValidationChange = fn;
}
// ...
}
Otherwise, if the child component shouldn't always be required, then you can inject the NgControl
from the child component, to check if it has the required
validator or not, using the AbstractControl.hasValidator() API which has been introduced in Angular 12.2.0 (Like how MatInput shows required asterisk when using required validator)
You can try the following to achieve that in this case:
@Component({
// ...
})
export class ChildComponent implements ControlValueAccessor {
get required(): boolean {
return this.ngControl?.control?.hasValidator(Validators.required);
}
constructor(@Optional() @Self() private ngControl: NgControl);
// ...
}