I have a situation using reactive forms and an input text.
I need to:
In order to execute the input validation only when the user leaves the input field I added "updateOn: 'blur'" to the validation options. The problem is that this affects not only when the validation is executed but also when the model will be updated. With 'blur' the model gets update only when the user leaves the input text and as a consequence the suggestion list is not working as user types as it should because the model is not being updated.
I added an example in stackblitz.
I would like to know if there is a way to execute the validation only on blur but the model to be updated as the user types.
Thanks.
I'm not aware of any built-in way of doing this, but here's one approach, which will use a custom value accessor.
@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); }
}
specialInput = new FormControl('', { updateOn: 'blur', validators: Validators.required });
<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.
I used a solution that I don't think is the best one but it solves my current issue.
When creating the form I'm not adding the validator anymore and I added a function that is executed on blur that add the validator to the FormControl, validate and remove the validator;
I can imagine that this solution is not the ideal one because I may have problems if I want to trigger the validation in a moment other than on blur but for my current scenario it works.
So this will be the form creation of the form:
const myInput = new FormControl('', validators: Validators.required })
This is the html
<input type="text" (blur)="validate()" formControlName="myInput">
And this is the validate function
validate(): void {
this.myInput.setAsyncValidators(this.myAsyncValidator());
this.myInput.updateValueAndValidity();
this.myInput.clearAsyncValidators();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With