I need to reach parents NgControl touch status in child component
// Parent Component Template
<form #myForm="ngForm">
<app-testing [(ngModel)]="value" name="testing"></app-testing>
<button (click)="validate()">Validate</button>
</form>
// Parent Component
validate() {
Object.keys(form.controls).forEach(key => {
form.controls[key].markAsTouched();
});
}
// TestingComponent
@Component({
selector: 'app-testing',
templateUrl: 'testing.component.html',
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TestingComponent),
multi: true
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => TestingComponent),
multi: true
}
]
})
export class TestingComponent implements ControlValueAccessor, Validator {
validate(control: AbstractControl): ValidationErrors {
this.isValid = false;
if (!this.value) {
return { required: true };
} else {
this.isValid = true;
return null;
}
}
value: number;
isValid: boolean = false;
isTouched: boolean = false;
writeValue(value: number): void {
this.value = value;
this.onChange(this.value);
}
onChange: (_: any) => void = (_: any) => {};
onTouched: () => void = () => {};
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
registerOnValidatorChange(fn: () => void): void {
this.onChange = fn;
}
}
Testing Component Template is as follows:
<input
type="text"
class="form-control"
[class.is-invalid]="!isValid && isTouched"
[(ngModel)]="value"
(ngModelChange)="onChange(value)"
(blur)="onTouched(); isTouched = true;"
/>
Before that I've tried to inject it directly
constructor(@Optional() @Self() public ngControl: NgControl) {
if (this.ngControl != null) {
this.ngControl.valueAccessor = this;
}
}
But I still can't subscribe to touch status change of ngControl
How would you do it? I've googled and found the way to extend FormControl with touchChanges observable https://stackoverflow.com/a/43381131/9590251 but I probably there is a better approach.
The best solution I've seen so far is here https://stackoverflow.com/a/44732590/9590251