I played around with this for a bit and I think that you are correct that you can't get this behavior out of the box with what the reactive forms give you. You can, however, make a directive that will bind to a new class which will allow you to set the styling the way you desire.
You create a directive that listens to the Blur event on the FormControl and when it occurs check to see if the field is invalid. If it is you can set your own class and then base the styles off of this.
Example:
@Directive({
selector: '[formControl]',
})
export class ValidationStatusDirective {
isValidated = false;
constructor(private el: ElementRef){}
@HostBinding('class.ng-validated') get ngValidated() { return this.isValidated; }
@HostBinding('class.ng-unvalidated') get ngUnvalidated() { return !this.isValidated; }
@HostListener('blur') validationStatusChanged(){
if(!this.isValidated &&
this.el.nativeElement.classList.contains('ng-invalid') &&
this.el.nativeElement.value.length > 0){
this.isValidated = true;
}
}
}
You then don't have to modify the HTML at all and then just set the styling when the input is both ng-invalid and ng-validated
For reference:
<input class="form-control"
[formControl]="name"
#input
placeholder="Enter 3 or more characters">
Styles:
input.ng-invalid.ng-validated{
border-color: red;
background-color: pink;
}
touchedbut stillpristine, only if the user types something, it will bedirty! Seems like fitting the case you listed.