Description of the issue
I'm working in a form where I have an async validation for a FormControl that is patched by another FormControl.
I'm using Angular Material with mat-form-field, mat-input and mat-error.
It has two inputs, the first one is to input a business name and it will automatically fill the second input with the slugified version of the name. The second input has an async validation where it checks against the backend if the slug is already in use.
The problem is when the user types a business name which its slug is already in use, the form status is "INVALID" (as expected), however it should display the styling of an invalid input on the second FormControl and it doesn't. If I click on the invalid field and click away it shows the FormControl as invalid but I want that behavior without clicking in the second Control.
Expected behavior
If the user types "Test Name" in the business name. The second FormControl show display the slugified version and the input should has the styling of an invalid control. As soon as the user changes the slugified version to "test-name2" it should be valid and show the normal styling for a valid input.
Example
I've created a Stackblitz where I've set up an example: https://stackblitz.com/edit/angular-ivy-r9nsk3?file=src/app/app.component.html
CodePudding user response:
As per official docs:
Errors are hidden initially and will be displayed on invalid form fields after the user has interacted with the element or the parent form has been submitted.
This means your FormControl
needs to be marked as touched.
You can do so by programmatically using this.form.get('businessSlug').markAsTouched();
after you set the value of the control.
CodePudding user response:
update the form input Tuched status here is the updated code
import { Component, OnDestroy, OnInit, VERSION } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { filter, map, SubscriptionLike, tap } from 'rxjs';
import { BusinessIdValidator } from './businessId.validator';
import urlSlug from 'url-slug';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit{
name = 'Angular ' VERSION.major;
subscriptions$: SubscriptionLike[] = [];
form = this.fb.group({
businessName: ['', [Validators.required]],
businessSlug: ['', [], [BusinessIdValidator.validator()]],
});
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.form.controls.businessName.valueChanges.subscribe((x) => {
this.form.controls.businessSlug.markAsTouched();
this.form.controls.businessSlug.setValue(urlSlug(x));
});
}
}