You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何取消Angular订单表单按回车键触发验证的行为

如何阻止Angular表单按下回车键自动触发表单验证

问题描述

我在Angular应用中创建了一个客户订单表单,希望仅在用户点击发送订单按钮时才触发表单验证。目前点击按钮验证正常,但用户按下回车键时会自动触发验证,需要避免该行为。

现有HTML代码

<form [formGroup]="orderForm">
  <div class="container form-container">
    <h4 class="container__title">{{ 'order.form.message.printout' | translate }}</h4>

    <!--Type de produit-->
    <div formArrayName="orders" ngDefaultControl>
      <div *ngFor="let order of ordersFormArray.controls; let i = index">
        <div [formGroupName]="i">
          <mat-form-field appearance="fill" class="A-form-field">
            <mat-label>{{
              'order.form.field.product' | translate
              }}</mat-label>
            <mat-select
              formControlName="produit"
              (selectionChange)="productChangeAction($event.value, i)"
            >

              <mat-option
                id="{{ 'label-option' + i }}"
                *ngFor="let product of productList"
                [value]="product.label"
              >
                {{ product.label }}
              </mat-option>
            </mat-select>
          </mat-form-field>

          <!--Documents associés au produit-->
          <mat-form-field appearance="fill" class="A-form-field">
            <mat-label>{{
              'order.form.field.documents' | translate
              }}</mat-label>
            <mat-select
              formControlName="document"
            >
              <mat-option
                *ngFor="let document of documents[i]"
                [value]="document.label"
              >
                {{ document.label }}
              </mat-option>
            </mat-select>
          </mat-form-field>

          <!--Quantité document commandé-->
          <mat-form-field appearance="fill" class="A-form-field">
            <mat-label>{{ 'order.form.field.maxQuantity' | translate }}</mat-label>
            <input matInput type="number" formControlName="quantite"/>
          </mat-form-field>

          <mat-icon (click)="removeOrder(i)">delete_outline</mat-icon>

          <mat-error
            *ngIf="ordersFormArray.controls[i]?.hasError('validateQuantity')">
            {{ 'order.form.message.documentsAuthorizedQuantityError' | translate: {
            maxQuantity: ordersFormArray.controls[i].getError('validateQuantity').max,
            documentLabel: ordersFormArray.controls[i].getError('validateQuantity').documentLabel
          } }}
          </mat-error>
        </div>
      </div>
    </div>

    <button mat-raised-button
            type="button"
            color="primary"
            data-test="add-order-button"
            (click)="addOrder()"
            class="add-order-button">
      <mat-icon>add</mat-icon>
      {{ 'order.form.button.addOrder' | translate }}
    </button>
  </div>

  <div class="container">
    <h4 class="container__title">{{ 'order.form.message.leaveComment' | translate }}</h4>
    <mat-form-field class="B-form-field" >
      <mat-label>{{ 'order.form.message.yourMessage' | translate }}</mat-label>
      <textarea matInput cdkTextareaAutosize #autosize="cdkTextareaAutosize" formControlName="message" maxlength="130"></textarea>
    </mat-form-field>
    <div class="buttons-right">
      <button type="button" class="order-button"
              mat-raised-button
              color="primary"
              [xenNavigationDirective]="goBackHome['link']"
              [routerLink]="userRealm + goBackHome['route']"
      >
        <mat-icon>not_interested</mat-icon>
        {{ 'order.form.button.cancel' | translate }}
      </button>

      <button type="submit" class="order-button"
              mat-raised-button
              color="primary"
              [disabled]="!orderForm.valid"
              (click)="onSendOrders()"
      >
        <mat-icon>check</mat-icon>
        {{ 'order.form.button.sendOrder' | translate }}
      </button>
    </div>

  </div>
</form>

现有TS提交方法

protected onSendOrders(): void {
  this.spinner.show();

  let order: ICommande = {
    message: this.orderForm.get('message')?.value,
    detail: this.ordersFormArray.value
  };
  this.order
    .sendOrders(order)
    .pipe(
      take(1),
      finalize(() => this.spinner.hide())
    )
    .subscribe({
      next: () => {
        this.notification.success('order.form.message.sendOrderSuccess');
      },
      error: () => {
        this.notification.error('order.form.message.sendOrderFail');
      }
    });
}

解决方案

方法一:修改提交按钮类型为button,手动触发表单验证

HTML中默认的type="submit"按钮会响应回车键触发表单提交,将其改为type="button"即可阻止该默认行为,同时在TS方法中手动触发表单验证:

  1. 修改提交按钮代码:
<button type="button" class="order-button"
        mat-raised-button
        color="primary"
        [disabled]="!orderForm.valid"
        (click)="onSendOrders()"
>
  <mat-icon>check</mat-icon>
  {{ 'order.form.button.sendOrder' | translate }}
</button>
  1. 在TS的onSendOrders方法开头添加手动验证逻辑:
protected onSendOrders(): void {
  // 标记所有表单控件为已触碰,触发验证提示
  this.orderForm.markAllAsTouched();
  // 表单无效则直接返回
  if (!this.orderForm.valid) {
    return;
  }

  this.spinner.show();

  let order: ICommande = {
    message: this.orderForm.get('message')?.value,
    detail: this.ordersFormArray.value
  };
  this.order
    .sendOrders(order)
    .pipe(
      take(1),
      finalize(() => this.spinner.hide())
    )
    .subscribe({
      next: () => {
        this.notification.success('order.form.message.sendOrderSuccess');
      },
      error: () => {
        this.notification.error('order.form.message.sendOrderFail');
      }
    });
}

方法二:阻止表单默认提交事件

如果希望保留按钮的type="submit"类型,可以在form标签上监听ngSubmit事件并阻止默认行为:

修改form标签:

<form [formGroup]="orderForm" (ngSubmit)="$event.preventDefault()">

这样回车键触发的表单提交会被阻止,只有点击按钮时才会执行onSendOrders方法。

原理说明

HTML表单的默认行为是:当表单内存在type="submit"的按钮时,按下回车键会自动触发表单的submit事件,进而触发Angular表单的验证逻辑。上述两种方法都是通过打破这个默认行为,让表单验证和提交仅由按钮点击触发。

内容的提问来源于stack exchange,提问作者Olivier

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 06:20:13