iT邦幫忙

2021 iThome 鐵人賽

DAY 9
2
Modern Web

Angular 常見問題大小事系列 第 9

Angular 冒泡事件

  • 分享至 

  • xImage
  •  

今天就來個說個在新手時期很常遇到,但卻不知為什麼會發生的問題

來看一下我們前幾天的表單範例,與圖上 console 的部份

在操控表單的時後,發現在點選新增欄位時,連submit 也一起被觸發了!
這是怎麼一回事呢!!!明明就沒有按送出呀!
原來是 JavaScript 裡的冒泡事件。
這對經驗豐富的前輩們來說,想必很快就能聯想到這之間的問題,但對還是新手時期的小嫩嫩,卻常常百思不得其解

而且在表單裡很常遇到這問題,原因是因為通常表單的架構都會是這樣


表單架構

.html

<!-- onSubmit -->
<form [formGroup]="form" (ngSubmit)="onSubmit()">
  <div
    formArrayName="favorites"
    *ngFor="let fav of favorites.controls; let idx = index"
  >
    <div [formGroupName]="idx">
      <ng-container *ngIf="idx === 0">
        <label for="">favorites:</label>
        <!-- 新增 Button -->
        <button (click)="addField()">新增</button>
        <br />
      </ng-container>
      <input formControlName="favorite" type="text" [value]="" />
      <button (click)="removeField(idx)">移除</button>
    </div>
  </div>
  <p style="color:red" *ngIf="form.errors?.phone">YOUR PHONE ERROR</p>
  <button type="submit">Submit</button>
</form>

在 onSubmit() 事件的裡面,還有著其他事件,新增移除,而當我點了新增按鈕後,同時也會觸發到 onSubmit() 這個事件

詳細機制可參考以下,這裡就不詳細說明了

重新認識 JavaScript: Day 14 事件機制的原理
DOM 的事件傳遞機制:捕獲與冒泡


事件預設行為

Angular 裡的 (click) 會有一些預設行為,
目標事件決定了 $event 物件的形態。如果目標事件是來自原生 DOM 元素的,那麼 $event 是一個DOM 事件物件,它具有 target 和 target.value 等屬性。

https://angular.tw/guide/event-binding-concepts#handling-events


該如何阻止它的行為產生呢?

在 html 裡直接阻擋

<button (click)="$event.preventDefault();addField()">新增</button>

在 ts 裡阻擋

.html

<button (click)="addField($event)">新增</button>

.ts

addField(e?: MouseEvent) {
  if (e) {
    e.preventDefault();
  }
}

以上兩個方式都可以。
把 click 的預設事件給阻檔掉就能避免其他事件被影響了!

今天的介紹就到此告一段落囉

參考資料:
事件繫結的工作原理
重新認識 JavaScript: Day 14 事件機制的原理
DOM 的事件傳遞機制:捕獲與冒泡


上一篇
Angular Reactive Forms 自訂表單驗証器
下一篇
Angular 下拉選單如何選定預設值
系列文
Angular 常見問題大小事31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
oaww
iT邦新手 5 級 ‧ 2022-12-28 15:46:36

type="button"不可以嗎?button預設是submit呀..

Mandy iT邦新手 2 級 ‧ 2023-09-21 13:49:28 檢舉

你好
若 type="button"
當按下送出時 (ngSubmit)="onSubmit()" 這裡就不會被觸發囉

我要留言

立即登入留言