首页 > 解决方案 > Angular,当用户单击按钮或多次提交时如何处理?

问题描述

如何防止用户多次提交表单?我目前的问题是当用户多次单击提交按钮时,它将创建多个用户。它应该只创建一次用户并在创建另一个用户之前等待。

这是我所拥有的:

<button mat-flat-button color="primary" [disabled]="userStatus == 'USER_EXISTS_ON_CURRENT_ACCOUNT'" (click)="createUser()">Create
                        User</button>

打字稿:

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;
      },
    });
  }

标签: angularjstypescriptmouseevent

解决方案


我稍微更新了你的代码,

1 - 我们必须在模板中创建一个用户按钮

    <button #createUserBtn mat-flat-button color="primary" [disabled]="userStatus == 'USER_EXISTS_ON_CURRENT_ACCOUNT'"> CreateUser </button>

2 - 访问 .ts 文件中的创建用户按钮

@ViewChild('createUserBtn', {static:true}) button;

3 - 创建变量clicks$来存储点击事件

clicks$: Observable<any>;

4 - 在 ngOnInit 中:初始化clicks$变量以监听点击事件

this.clicks$ = fromEvent(this.button.nativeElement, 'click');

5 - 在 ngOnInit 中:在每个点击事件上,即从click$我们将我们的事件传递给exhaustMap

排气映射的美妙之处在于,一旦第一个(外部可观察)事件被触发,它将停止监听事件(外部可观察),直到完成其内部可观察

所以在我们的例子中,当用户第一次点击按钮(事件)时,exhaustMap将停止监听按钮点击事件,直到它完成我们的 API 调用createUser()。我们将使用该handleResponse()方法处理这个 API 调用 observable。

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());
}

创建用户 API 调用

createUser(): Observable<any> {
    return this.accountService.create(this.modelForm.value).pipe(
      finalize(() => (this.isInProgress = false))
    );
  }

处理响应

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;
    };
  }

演示

如果您无法访问按钮,您可以将 ngOnit 代码移动到AfterViewInit 让我知道是否有任何错误,因为我尚未完全测试您的代码。

 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());
  }

推荐阅读