I am using the same component for read/edit routines. async-validator
works perfectly with new entries. the problem starts if the user accidentally changes the value and tries to revert back to the saved value. my current code will run regardless and returns the value as existing. I want to pass more data along with control value so I can validate if that pair value exist already or not.
I am posting the relevant code,
this is my form control
,
patientEmail: new FormControl(
null,
[Validators.email, Validators.required],
FormControlValidator.createEmailAsyncValidator(
this.asyncValidatorService
),
),
my async validator creator class is,
export class FormControlValidator {
static createEmailAsyncValidator(asyncValidatorService: AsyncValidationService) {
return (control: AbstractControl) => {
if (!control.pristine) {
control.markAsPristine();
return asyncValidatorService
.validateEmailNotTaken(control)
.map((response: HttpResponse<boolean>) => {
return !response.body ? null : { taken: true };
});
}
return Observable.of(null);
};
}
and finally my service,
@Injectable()
export class AsyncValidationService {
constructor(private httpService: HttpClientService) {}
public validateEmailNotTaken(control: AbstractControl) {
return this.httpService.getRequest(
'PatientsRegistration/IsPatientEmailExist?email=' + control.value,
);
}
}
I want to be able to pass another param to my createEmailAsyncValidator
, something like another control value from the form if possible.
A validator function returns true if the form field is valid according to the validator rules, or false otherwise. A validator can be plugged in directly into a reactive form simply by adding it to the validators list. Each form field has its own list of separate validators.
Angular does not provide built-in type async Validation implmentation, it provides only for sync validation. The implementation of async validator is very similar to the sync validator. The only difference is that the async Validators must return the result of the validation as an observable or as Promise.
Synchronous and asynchronous Validators are very similar - the main difference is that a sync Validator returns an error object instance directly, while the async version returns an Observable of the the same object. The most common use case for async Validators is doing a server validation via an HTTP Callback.
If you need to validate control based on another control, you need to lift the validator to the parent control. Here's an example of validator that checks if the email starts with person's name (another control value).
app.component.ts
import { Component } from '@angular/core';
import {FormBuilder, FormControl, FormGroup, ValidatorFn} from '@angular/forms'
const personalEmailValidator: ValidatorFn = (ctrl: FormGroup) => {
const email = ctrl.get('email') as FormControl;
const name = ctrl.get('name') as FormControl;
const valid = (email.value || '').startsWith(name.value);
return valid ? null : { personalEmailError: 'Email must start with a person name'}
}
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
form: FormGroup;
constructor(private fb: FormBuilder) {
this.form = this.fb.group({
email: [null],
name: [null]
}, { validator: personalEmailValidator })
}
}
app.component.html
<input [formControl]="form.get('name')" placeholder="name" />
<input [formControl]="form.get('email')" placeholder="email" />
{{ form.hasError('personalEmailError') ? form.getError('personalEmailError') : 'form is valid'}}
Live demo
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