Issue
How can I prevent users from submitting a form multiple times? My current issue right now is when the user clicked the submit button multiple times it will create multiple users. It should create a user only once and wait before creating another user.
Here is what I have:
<button mat-flat-button color="primary" [disabled]="userStatus == 'USER_EXISTS_ON_CURRENT_ACCOUNT'" (click)="createUser()">Create
User</button>
TypeScript:
createUser() {
this.accountService.create(this.modelForm.value).pipe(
finalize(() => {
this.isInProgress = false;
})
).subscribe({next: (res) => { this.notificationService.showSuccess('User has been created successfully.');
this._router.navigate(['settings/user']);
},
error: (err) => {this.notificationService.showError('Something went wrong, Try again later.');
this.isInProgress = false;
},
complete: () => {
this.isInProgress = false;
},
});
}
Solution
I have slightly updated your code,
1 - We will have to create a User button in the template And
<button #createUserBtn mat-flat-button color="primary" [disabled]="userStatus == 'USER_EXISTS_ON_CURRENT_ACCOUNT'"> CreateUser </button>
2 - Access Create User button in .ts file
@ViewChild('createUserBtn', {static:true}) button;
3 - Create variable clicks$
to store click events
clicks$: Observable<any>;
4 - In ngOnInit: Initialize clicks$
variable to listen click events
this.clicks$ = fromEvent(this.button.nativeElement, 'click');
5 - In ngOnInit: On every click event i.e from click$
we will pass our event to exhaustMap
The beauty of exhaustMap is once the first (outer observable) event is triggered it will stop listening to events(Outer Observable) untill it completes its inner observable
So in our case when the user clicks on the button the first time(event), the exhaustMap
will stop listening to the button click events until it completes our API call createUser()
. This API call observable we will handle using the handleResponse()
method.
ngOnInit() {
this.clicks$ = fromEvent(this.button.nativeElement, 'click');
const result$ = this.clicks$.pipe(
tap(x => console.log('clicked.')),
exhaustMap(ev => {
console.log(`processing API call`);
return this.createUser();
})
);
result$.subscribe(this.handleResponse());
}
Create User API Call
createUser(): Observable<any> {
return this.accountService.create(this.modelForm.value).pipe(
finalize(() => (this.isInProgress = false))
);
}
To handle response
handleResponse(): any {
return {
next: res => {
this.notificationService.showSuccess('User has been created successfully.');
this._router.navigate(['settings/user']);
},
error: err => {
this.notificationService.showError('Something went wrong, Try again later.');
this.isInProgress = false;
}
complete: () => this.isInProgress = false;
};
}
If you can't access button you can move ngOnit Code to AfterViewInit
Let me know if there is any error because i have not fully tested your code.
ngAfterViewInit(): void {
fromEvent(this.button.nativeElement, 'click')
.pipe(
tap(x => console.log('clicked.')),
exhaustMap(ev => {
console.log(`processing API call`);
return this.createUser();
})
)
.pipe(tap(x => console.log('Api call completed....')))
.subscribe(this.handleResponse());
}
Answered By - navnath
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.