【问题标题】:Angular , how to handle when user click button or submit multiple times?Angular,当用户单击按钮或多次提交时如何处理?
【发布时间】:2021-11-06 02:03:34
【问题描述】:

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

这是我所拥有的:

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

【问题讨论】:

  • 该功能是否应该限制用户点击,直到 API 响应先前点击事件的值?或者只是限制用户在“n”秒内再次单击该按钮?

标签: angularjs typescript mouseevent


【解决方案1】:

我稍微更新了你的代码,

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 的美妙之处在于,一旦触发第一个(外部可观察的)事件,它就会停止 监听事件(外部 Observable)直到它完成其内部 observable

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

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

Demo

如果您无法访问按钮,您可以将 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());
  }

【讨论】:

  • 为什么会在初始化时触发? ,它应该只在单击按钮时创建用户先生
  • 它正在调用页面加载
  • 查看演示。弄清楚有什么不同。否则分享您的oninit 代码
  • 如果你在 stackBlitz 上分享那个场景,我可以找出问题所在
  • 触发this.notificationService.showError('出了点问题,稍后再试。'); ,
【解决方案2】:

如果您想要的功能是应限制用户再次单击按钮,直到 API 响应先前单击事件的值,您可以执行以下操作,

在您的 component.html 文件中,

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

在您的 component.ts 文件中,

  • 创建一个布尔类型变量,初始值设置为 false。 disableUserCreation: boolean = false;

  • 创建以下函数,

isButtonDisabled(): boolean {
    if (this.userStatus == 'USER_EXISTS_ON_CURRENT_ACCOUNT' || this.disableUserCreation) {
        return true;
    }
    return false;
}

那么,

createUser() {
    this.disableUserCreation = true;
    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;
        this.disableUserCreation = false;
      },
    });
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-11
    • 2021-08-02
    • 2015-01-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多