Reputation: 2244
I have an email field, and I added two validators(required, email), I want to check validation status on the input event
to call API check dose a member of my system when it's valid, if it's invalid
don't to call API and don't show error message on the page.
I will show error message on blur event(focusOut email's input),firstly I used formControl.validator(formControl)
to trigger validators and check formControl.valid
,I got valid status successful but it will show error message on the page because I subscribed statsuChange
to show an error message when status equal to invalid.
currently, I save validators in a variable and pass to initEmailChaingeEvent()
to check validation status without statusChange event.
It's can work, but I think it's not a good way, here's an example of my implementation:
export class AppComponent {
public sampleForm: FormGroup;
@ViewChild('emailElm')
emailElm: ElementRef;
ngOnInit() {
this.initForm();
}
initForm() {
const emailValidtors = [
Validators.required,
Validators.email
]
const emailFC = new FormControl(null, {
validators: emailValidtors,
updateOn: 'blur'
});
//
this.sampleForm = new FormGroup({
'email': emailFC
});
//
this.initEmailChaingeEvent({
emailFC: emailFC,
validtors: emailValidtors
});
//
this.sampleForm.valueChanges.subscribe((val) => {
console.log('_blue event:valueChanges', val)
});
//
this.initShowErrorMsgEvent({
fc: emailFC
});
}
private initEmailChaingeEvent(arg: {
emailFC: FormControl,
validtors: any[]
}) {
fromEvent(this.emailElm.nativeElement, 'input')
.pipe(debounceTime(500))
.subscribe((event: Event) => {
const currentEmail = (event.target as HTMLInputElement).value;
// check is valid
// **quention** : how can I get validtors from fromcontrol self
// if I use arg.emailFC.validator(arg.emailFC) to ehcek status , it will trigger oberservable in initShowErrorMsgEvent(),
// but I just want to got valid result , I don't want to show error msg on UI at this time
for (const validator of arg.validtors) {
const inValid = validator(arg.emailFC);
if (inValid) {
console.log('input event:invalid', currentEmail);
return;
}
}
// **do sometheng when all valid**
console.log('input event:call API , email:',currentEmail );
});
}
private initShowErrorMsgEvent(arg: {
fc: FormControl,
}) {
arg.fc.statusChanges
.subscribe((status) => {
// console.log('status' , status);
if (status === 'INVALID') {
// show error msg....
console.log('_show error msg by antoher component');
}
});
}
}
<form [formGroup]="sampleForm">
<input formControlName="email" #emailElm >
</form>
Upvotes: 9
Views: 6682
Reputation: 2244
thanks everyone give me more idea,I fixed it through formControl's validator property,it's my modifyed list:
private initEmailChaingeEvent(arg:{
emailFC : FormControl,
....
}) {
...
const inValid = arg.emailFC.validator({
value: currentEmail
}
as any);
....
}
Upvotes: 0
Reputation: 3616
You over-complicated the task. First, declare your form, and control validators. If you compose a validator from a list of validators, they will be checked in order of definition. So, first the required, then "if it's valid email", and last you custom validator will check if it's unique
....
this.emailForm = this.fb.group({
emailAddress: [null, Validators.compose([Validators.required, Validators.email, uniqueEmailValidator()])]
});
...
Then you create your custom validator for checking the user email by the API. More info on custom validators: Angular docs
function uniqueEmailValidator(){
...
}
Upvotes: 2
Reputation: 896
There's a lot going on here that needs some work. First off, I'd subscribe to the formValue changes of the control instead of using an Observable on the native element.
this.sampleForm.get('email').valueChanges.subscribe((event) => {
// CODE IN HERE
}
ValueChanges is a property on the formControl that emits an event when the value changes. https://angular.io/api/forms/AbstractControl
Next, to access the validators, you can simply check the form control if it is valid.
this.sampleForm.get('email').valid();
If any validator is invalid, this will be false, if all validators are valid, it will be true.
EDIT:
From your comment, sounds like you want a debounceTime pipe in there:
this.sampleForm.get('email').valueChanges
.pipe(debounceTime(500), distinctUntilChanged())
.subscribe((event) => {
if (this.sampleForm.get('email').valid) {
// Your API logic here
}
}
DebounceTime basically delays the event from being processed and will throw out any pending events in the queue.
debounceTime delays values emitted by the source Observable, but drops previous pending delayed emissions if a new value arrives on the source Observable. http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-debounceTime
Upvotes: 0