I'm not aware of any built-in way of doing this, but here's one approach, which will use a custom value accessor.
custom-input.component.ts
@Component({
selector: 'app-custom-input',
template: `
<p>
custom input:
<input
#i
(input)="onChangeFn($event.target.value)"
(blur)="onTouchedFn()"
type="text"
[formControl]="input"
>
</p>
<p>
inner input value: {{ i.value }}
</p>
`,
providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: CustomInputComponent, multi: true, } ]
})
export class CustomInputComponent implements OnInit, ControlValueAccessor {
input: FormControl;
onTouchedFn: Function;
onChangeFn: Function;
constructor(private fb: FormBuilder) { }
ngOnInit() {
this.input = this.fb.control('');
}
registerOnChange (fn) {
this.onChangeFn = fn;
}
registerOnTouched (fn) {
this.onTouchedFn = fn;
}
writeValue (v) { this.input.setValue(v); }
}
parent.component.ts
specialInput = new FormControl('', { updateOn: 'blur', validators: Validators.required });
parent.component.html
<app-custom-input [formControl]="specialInput"></app-custom-input>
<p>
Special input validation status: {{ specialInput.valid || 'false' }}
</p>
You can think of your form controls as a tree structure:
FG - FormGroup; FC - FormControl
FG
/ | \
FC FC FC
In your case, when FC has changed its value(e.g due to user input), all its descendants(in this case FG, but in a complex example there could be more) will have to be updated as well, regardless of their updateOn value.
By following this approach, this tree would now look like this(assuming the last FC is built this way):
FG
/ | \_________
FC FC | FC |
| \ |
| FC <-- the `input` elem. in the custom component
|_________|
As a result, the value will update onChange in the inner FC, and onBlur in the outer FC.
StackBlitz.
Also, if you'd like to read more about forms, I'd recommend checking out this article.