Event Binding
| 対応: | Angular 14(2022) |
|---|
『Angular』のイベントバインディング(Event Binding)は、テンプレート上のDOMイベントをコンポーネントのメソッドに紐付ける構文です。(イベント名)="ハンドラ()" の丸括弧記法を使い、クリックや入力・フォーム送信などのユーザー操作をコンポーネントのロジックで処理できます。
基本的な使い方
| 記法 | 説明 |
|---|---|
(イベント名)="ハンドラ()" | DOMイベントが発生したときにコンポーネントのメソッドを呼び出します。 |
(イベント名)="ハンドラ($event)" | $event オブジェクトをメソッドに渡し、イベントの詳細情報を取得します。 |
(イベント名)="プロパティ = 値" | メソッドを経由せず、テンプレート内でインラインに代入式を書くこともできます。 |
(click)="doSomething()" | クリックイベントをハンドラに紐付ける最も典型的な例です。 |
(input)="onInput($event)" | テキスト入力のたびに呼び出され、入力値を取得できます。 |
(submit)="onSubmit()" | フォームの送信イベントをハンドラに紐付けます。 |
クリックイベントの基本
// app.component.ts
// (click)="メソッド()" の形でクリックイベントをコンポーネントのメソッドに紐付けます
import { Component } from '@angular/core';
@Component({
standalone: true,
selector: 'app-root',
// ---- HTMLテンプレート部分 ----
// (click)="increment()" → ボタンをクリックするたびに increment() が呼ばれます
// (click)="decrement()" → ボタンをクリックするたびに decrement() が呼ばれます
// (click)="reset()" → ボタンをクリックするとカウンターを0に戻します
template: `
<p>カウント: {{ count }}</p>
<button (click)="increment()">+1</button>
<button (click)="decrement()">-1</button>
<button (click)="reset()">リセット</button>
`,
})
export class AppComponent {
// 現在のカウント値です
count: number = 0;
// カウントを1増やします
increment(): void {
this.count++;
}
// カウントを1減らします
decrement(): void {
this.count--;
}
// カウントを0に戻します
reset(): void {
this.count = 0;
}
}
$event でイベントオブジェクトを受け取る
// app.component.ts
// (イベント名)="ハンドラ($event)" の形で、イベントオブジェクトをメソッドに渡せます
// $event はブラウザのネイティブ DOM イベントオブジェクト(MouseEvent・InputEvent など)です
import { Component } from '@angular/core';
@Component({
standalone: true,
selector: 'app-root',
// ---- HTMLテンプレート部分 ----
// (click)="onClick($event)" → クリック位置の座標などを取得します
// (input)="onInput($event)" → テキスト入力のたびに入力値を取得します
// (keydown)="onKeyDown($event)" → 押されたキーの情報を取得します
template: `
<button (click)="onClick($event)">クリック情報を取得</button>
<p>クリック位置: {{ clickInfo }}</p>
<input type="text" (input)="onInput($event)" placeholder="文字を入力してください" />
<p>入力値: {{ inputValue }}</p>
<input type="text" (keydown)="onKeyDown($event)" placeholder="キーを押してください" />
<p>押されたキー: {{ pressedKey }}</p>
`,
})
export class AppComponent {
// クリック位置の情報を表示する文字列です
clickInfo: string = '(未クリック)';
// テキスト入力の現在値です
inputValue: string = '';
// 最後に押されたキーの名前です
pressedKey: string = '';
// クリックイベントのハンドラです。クリック座標を取得します
onClick(event: MouseEvent): void {
this.clickInfo = 'X: ' + event.clientX + ', Y: ' + event.clientY;
}
// 入力イベントのハンドラです。input要素の現在値を取得します
onInput(event: Event): void {
// event.target を HTMLInputElement にキャストして value を取得します
const target = event.target as HTMLInputElement;
this.inputValue = target.value;
}
// キーダウンイベントのハンドラです。押されたキーの名前を取得します
onKeyDown(event: KeyboardEvent): void {
this.pressedKey = event.key;
}
}
フォームの送信イベント
// app.component.ts
// (submit)="ハンドラ($event)" でフォーム送信を捕捉します
// $event.preventDefault() を呼ぶことでページのリロードを防ぎます
import { Component } from '@angular/core';
@Component({
standalone: true,
selector: 'app-root',
// ---- HTMLテンプレート部分 ----
// (submit)="onSubmit($event)" → フォームが送信されたときにハンドラを呼び出します
// (input)="onNameInput($event)" → 名前欄への入力をリアルタイムに取得します
// (input)="onEmailInput($event)" → メール欄への入力をリアルタイムに取得します
template: `
<form (submit)="onSubmit($event)">
<label>
名前:
<input type="text" (input)="onNameInput($event)" />
</label>
<label>
メール:
<input type="email" (input)="onEmailInput($event)" />
</label>
<button type="submit">送信</button>
</form>
<p *ngIf="submitted">
送信内容 — 名前: {{ name }}、メール: {{ email }}
</p>
`,
})
export class AppComponent {
// フォームに入力された名前です
name: string = '';
// フォームに入力されたメールアドレスです
email: string = '';
// フォームが送信済みかどうかを表すフラグです
submitted: boolean = false;
// 名前欄の入力イベントハンドラです
onNameInput(event: Event): void {
const target = event.target as HTMLInputElement;
this.name = target.value;
}
// メール欄の入力イベントハンドラです
onEmailInput(event: Event): void {
const target = event.target as HTMLInputElement;
this.email = target.value;
}
// フォーム送信のハンドラです。デフォルト動作(ページリロード)をキャンセルします
onSubmit(event: Event): void {
event.preventDefault();
this.submitted = true;
console.log('送信された名前:', this.name);
console.log('送信されたメール:', this.email);
}
}
インライン式でシンプルに書く
// app.component.ts
// 処理が単純な場合は、メソッドを定義せずにテンプレート内で直接代入式を書けます
// ただし複雑なロジックはコンポーネント側のメソッドに書くことを推奨します
import { Component } from '@angular/core';
@Component({
standalone: true,
selector: 'app-root',
// ---- HTMLテンプレート部分 ----
// (click)="isVisible = !isVisible" → クリックのたびに表示状態を切り替えます(インライン式)
// (mouseenter)="isHovered = true" → マウスが乗ったとき hovered 状態にします
// (mouseleave)="isHovered = false" → マウスが離れたとき hovered 状態を解除します
template: `
<button (click)="isVisible = !isVisible">
{{ isVisible ? '非表示にする' : '表示する' }}
</button>
<p *ngIf="isVisible">表示中のコンテンツです</p>
<div
(mouseenter)="isHovered = true"
(mouseleave)="isHovered = false"
[style.background]="isHovered ? 'lightyellow' : 'white'"
style="padding: 16px; border: 1px solid #ccc;"
>
マウスを乗せると背景色が変わります
</div>
`,
})
export class AppComponent {
// コンテンツの表示・非表示状態です
isVisible: boolean = true;
// マウスが要素上にあるかどうかを表す状態です
isHovered: boolean = false;
}
キーボードイベントのフィルタリング
// app.component.ts
// (keydown.キー名)="ハンドラ()" の形で、特定のキーが押されたときだけ発火させられます
// Enter キーや Escape キーなど、よく使うキーを簡潔に指定できます
import { Component } from '@angular/core';
@Component({
standalone: true,
selector: 'app-root',
// ---- HTMLテンプレート部分 ----
// (keydown.enter)="onEnter()" → Enter キーが押されたときだけ onEnter() を呼び出します
// (keydown.escape)="onEscape()" → Escape キーが押されたときだけ onEscape() を呼び出します
// (keydown.ArrowUp)="onUp()" → 上矢印キーが押されたときに onUp() を呼び出します
// (keydown.ArrowDown)="onDown()" → 下矢印キーが押されたときに onDown() を呼び出します
template: `
<input
type="text"
(keydown.enter)="onEnter()"
(keydown.escape)="onEscape()"
placeholder="Enter で確定、Escape でキャンセル"
/>
<p>状態: {{ status }}</p>
<p>カーソル位置: {{ cursorIndex }}</p>
<div tabindex="0" (keydown.ArrowUp)="onUp()" (keydown.ArrowDown)="onDown()"
style="border:1px solid #ccc; padding:8px; width:200px;">
上下矢印キーで操作できます(フォーカスしてから押してください)
</div>
`,
})
export class AppComponent {
// 操作の状態を表示する文字列です
status: string = '待機中';
// 矢印キーで動かす仮想カーソルの位置です
cursorIndex: number = 0;
// Enter キーが押されたときのハンドラです
onEnter(): void {
this.status = '確定しました';
}
// Escape キーが押されたときのハンドラです
onEscape(): void {
this.status = 'キャンセルしました';
}
// 上矢印キーが押されたときのハンドラです
onUp(): void {
this.cursorIndex--;
}
// 下矢印キーが押されたときのハンドラです
onDown(): void {
this.cursorIndex++;
}
}
主なDOMイベント一覧
| イベント名 | 発生タイミング | テンプレート例 |
|---|---|---|
click | 要素がクリックされたとき。 | (click)="onClick()" |
dblclick | 要素がダブルクリックされたとき。 | (dblclick)="onDblClick()" |
input | テキスト入力などの値が変化したとき(リアルタイム)。 | (input)="onInput($event)" |
change | フォーム要素の値が確定して変化したとき。 | (change)="onChange($event)" |
submit | フォームが送信されたとき。 | (submit)="onSubmit($event)" |
keydown | キーが押し下げられたとき。 | (keydown)="onKeyDown($event)" |
keyup | キーが離されたとき。 | (keyup)="onKeyUp($event)" |
mouseenter | マウスポインタが要素に入ったとき。 | (mouseenter)="onEnter()" |
mouseleave | マウスポインタが要素から出たとき。 | (mouseleave)="onLeave()" |
focus | 要素がフォーカスを得たとき。 | (focus)="onFocus()" |
blur | 要素がフォーカスを失ったとき。 | (blur)="onBlur()" |
概要
『Angular』のイベントバインディング((イベント名)="ハンドラ()")は、テンプレートのDOMイベントをコンポーネントのメソッドに紐付けるための構文です。$event を使うとネイティブのイベントオブジェクトをメソッドに渡して詳細情報を取得でき、(keydown.enter) のようにキー名をドットの後に指定すると特定のキーだけに反応させることもできます。
単純な処理であればテンプレート内でインライン式として書くこともできますが、ロジックが複雑になる場合はコンポーネント側にメソッドとして切り出すと可読性と保守性が高まります。
イベントバインディングはデータバインディングの重要な要素のひとつです。プロパティへの反映と組み合わせた双方向バインディングについては データバインディング や プロパティバインディング もあわせてご覧ください。
よくあるミス: $event を渡し忘れてイベント情報が取れない
イベントオブジェクト(クリック座標・入力値・キー情報など)をメソッドで使いたい場合は、テンプレートで $event を引数として渡す必要があります。渡し忘れると、メソッドの引数は undefined になります。
// NG: $event を渡していないのにメソッドで使おうとしている
template: `
<input type="text" (input)="onInput()" />
`,
export class AppComponent {
onInput(event: Event): void {
// event は undefined になる
const target = event.target as HTMLInputElement;
console.log(target.value);
}
}
// OK: テンプレートで $event を渡す
template: `
<input type="text" (input)="onInput($event)" />
`,
export class AppComponent {
onInput(event: Event): void {
const target = event.target as HTMLInputElement;
console.log(target.value);
}
}
よくあるミス: イベント名を間違えて発火しない
Angular のイベントバインディングは DOM のネイティブイベント名を小文字で使います。よくある間違いは onChange や onClick のように camelCase で書くことです。正しくは change や click です。
// NG: camelCase で書いている(イベントが発火しない) template: ` <input type="text" (onChange)="handleChange($event)" /> <button (onClick)="handleClick()">送信</button> `,
// OK: DOM のネイティブイベント名はすべて小文字 template: ` <input type="text" (change)="handleChange($event)" /> <button (click)="handleClick()">送信</button> `,
よくあるミス: フォーム送信でページがリロードされる
<form> の送信イベントを処理する場合、event.preventDefault() を呼ばないとブラウザのデフォルト動作(ページリロード)が実行されます。呪術廻戦の五条悟がお問い合わせフォームを送信する例で確認します。
// NG: preventDefault() を呼んでいないのでページがリロードされる
template: `
<form (submit)="onSubmit()">
<button type="submit">送信</button>
</form>
`,
export class AppComponent {
onSubmit(): void {
// ここに到達する前にページがリロードされてしまう
console.log('送信完了');
}
}
// OK: $event を受け取って preventDefault() を呼ぶ
template: `
<form (submit)="onSubmit($event)">
<input type="text" placeholder="お名前" (input)="onNameInput($event)" />
<button type="submit">送信</button>
</form>
<p *ngIf="submitted">{{ senderName }} からのお問い合わせを受け付けました</p>
`,
export class AppComponent {
senderName: string = '';
submitted: boolean = false;
onNameInput(event: Event): void {
const target = event.target as HTMLInputElement;
this.senderName = target.value;
}
onSubmit(event: Event): void {
event.preventDefault();
this.submitted = true;
console.log('送信者:', this.senderName);
}
}
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。