如何在Angular2中处理双重提交 [英] How to deal with double submit in Angular2

查看:277
本文介绍了如何在Angular2中处理双重提交的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我快速单击提交按钮,则该表单将被提交两次或两次以上.我的想法是通过禁用属性来防止这种情况,但是我需要像这样的每种形式的变量disableButon:

If I click fast on my submit-button the form is submitted two or more times. My thought was to prevent this with the disabled attribute, but I need variable disableButon in every form like this:

@Component({
    selector: 'example',
    template: `
      <form (submit)="submit()" >
        <--! Some Inputs -->
        <button [disabled]="disableButton" type="submit">Submit<button>
      </form>
       `
  })
  export class ExampleComponent {
    private disableButton: boolean = false;
    .......
    submit(){
      this.disableButton = true;
      /*
      * API call
      */
      this.disableButton = false;
    }
  }

我是正确执行此操作还是有一种更有效/更优雅的方法?

Am I doing this right or is there a more efficent/elegant way to do it?

推荐答案

重复提交交易很容易错误.在具有<form #theForm="ngForm" (ngSubmit)="submit()">的表单上:

Dealing with double-submission is easy to do wrong. On a form with <form #theForm="ngForm" (ngSubmit)="submit()">:

<button type="submit" [disabled]="theForm.submitted" />仅在不存在任何验证的情况下才起作用.按下按钮时(而不是在表单通过验证之后),Angular的ngForm.submitted设置为true. (NgForm的已提交"属性实际上表示试图提交".)

<button type="submit" [disabled]="theForm.submitted" /> would only work if no validation whatsoever was present. Angular's ngForm.submitted is set to true when the button is pressed, not after the form passes validation. (NgForm's "submitted" property actually means "tried to submit".)

<button type="submit" [disabled]="theForm.submitted && theForm.valid" />并不更好:提交时遇到验证错误后,用户修复验证错误后,当提交按钮重新提交时,提交"按钮即自动禁用.

<button type="submit" [disabled]="theForm.submitted && theForm.valid" /> isn't much better: after getting validation errors on submission, the moment the user fixes the validation errors, the submit button disables itself right as they're reaching for it to re-submit.

直接或通过组件的submit()中的ngForm.resetForm()重置ngForm.submitted是一个糟糕的选择,因为submitted是您的主要变量,用于控制是否显示验证错误消息以及在何处显示验证错误消息.

Resetting ngForm.submitted either directly or via ngForm.resetForm() within your component's submit() is a poor option, since submitted is your primary variable controlling whether and where the validation error messages are displayed.

真正的问题:Angular无法知道submit()中的API调用何时或是否失败.即使Angular提供了一个属性,该属性意味着只需单击Submit按钮,它也通过了所有验证",就可以在该属性上挂起[disabled] ="thatProperty",但是Angular不知道何时设置属性 back ,例如当您的API调用错误,并且您想让用户再次按Submit来重试服务器时.

The real problem: Angular has no way to know when or whether your API calls in submit() failed or succeeded. Even if Angular provided a property that meant "just clicked Submit button and it also passed all validation" on which you can hang [disabled]="thatProperty", Angular wouldn't know when to set the property back, such as when your API call errors out and you'd like to let the user press submit again to re-try the server.

也许Angular可能会禁止所有提交函数采用() => Observable<boolean>的形式,并且它可以订阅您提交的成功或失败,但是似乎仅仅为了在框架中重置一个布尔值就显得过高了.

Perhaps Angular might proscribe all submit functions to be of the form () => Observable<boolean> and it could subscribe to your submit's success or failure, but it seems overkill just to reset a boolean in the framework.

因此,您必须在所有API调用完成后采取行动,并以某种方式通知Angular提交按钮已准备好重用.该操作要么是设置已经在执行的显式布尔值,要么是强制禁用.

So you must take action after all your API calls are finished and inform Angular somehow that the submit button is ready for reuse. That action is either going to be setting the explicit boolean you are already doing, or imperatively disabling.

这是在没有布尔值的情况下必须执行的操作.

向提交按钮添加模板引用变量,例如#submitBtn:

Add a template reference variable like #submitBtn to the submit button:

<button type="submit" #submitBtn class="green">Go!</button>

将其传递到组件的submit():

<form (ngSubmit)="submit(submitBtn)" ...>

接受并在组件端使用它:

Accept and use it component-side:

submit(submitBtn: HTMLButtonElement): void {
    submitBtn.disabled = true;
    /// API calls
    submitBtn.disabled = false;
}

如果您的API调用有多个共享相同错误处理程序的路径,则也需要将HTMLButtonElement传递给它们,因为使用this.disableButton它们将无法再将其从组件中抽出.

And if your API calls have multiple pathways that share a common error-handler, you'd need to pass the HTMLButtonElement on through to them as well, since they can no longer pluck it out of the component with this.disableButton.

(或者,您已经声明了#theForm,而不是声明并传递#submitBtn,所以将其传递为:NgForm,组件代码可以向下钻取按钮...或整个表单的覆盖层,或其他任何内容.)

(Alternately, instead of declaring and passing #submitBtn, you already have #theForm declared, so pass that instead as :NgForm, and component code can drill-down to the button... or to an overlay over the whole form, or whatever.)

此解决方案是否比声明另一个与ngForm.submitted稍有不同的布尔值更优雅,但事实是Angular不知道组件的Submit()及其所有异步过程何时完成而没有订阅.

Whether this solution is more or less elegant than declaring another boolean that works slightly differently than ngForm.submitted is opinion, but it is fact that Angular can't know when the component's submit() and all its async processes are finished without a subscription.

这篇关于如何在Angular2中处理双重提交的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆