9/7まで 最大30%OFF 初心者編|無料コーディング教材|HTML・CSS・jQueryを実践で学ぶ

jQueryのchangeイベントの使い方|フォーム別の発火タイミングを初心者向けに解説

jQuery changeの使い方を示すアイキャッチ

フォームの値が変わったときに表示を更新したいけれど、「changeはいつ動くの?」「文字を入力してもすぐ反応しない」と迷うことがありますよね。

jQueryでは、対象要素へ.on('change', handler)を設定すると、入力値や選択値が変更されたタイミングで処理を実行できます。現在は、非推奨の.change(handler)ではなく.on()を使うのが基本です。

$('#target').on('change', function () {
  const value = $(this).val();
  console.log(value);
});

ただし、テキスト入力とセレクトボックスでは発火するタイミングが異なります。この記事では、テキスト、select、radio、checkboxを実際に動かした画面とコードで確認します。

jQueryのchangeイベントとは

changeは、フォーム部品の値が変更されたことを検知するイベントです。主に<input><textarea><select>へ設定します。

フォーム部品changeが発火するタイミング
テキスト入力・textarea値を変更してフォーカスを外したとき
select別の選択肢を選んだとき
radio別のラジオボタンを選んだとき
checkboxチェック状態を切り替えたとき

テキスト入力で「1文字入力するたびに処理したい」場合は、changeではなくinputイベントを使います。次の図で、発火タイミングの違いを確認してください。

changeとinputイベントの発火タイミングの違い

テキストの入力確定後にチェックするならchange、検索候補や文字数を入力中に更新するならinput、というように目的で使い分けます。

changeイベントの基本構文

基本構文は「対象要素を選ぶ→changeイベントを登録する→変更時の処理を書く」という順番です。

$('セレクタ').on('change', function (event) {
  // 値が変更されたときの処理
});

function内のthisは、実際に変更されたHTML要素です。$(this).val()と書くと、その要素の現在値を取得できます。

引数のeventにはイベント情報が入ります。event.targetも変更元の要素を指すため、$(event.target).val()でも値を取得できます。

以前よく使われていた次の短縮形は、jQuery 3.3で非推奨になっています。

// 非推奨の短縮形
$('#target').change(function () {
  console.log($(this).val());
});

// 推奨する書き方
$('#target').on('change', function () {
  console.log($(this).val());
});

.on()はイベント名が明確で、複数イベントやイベント委譲にも同じ書き方を使えます。新しく書くコードは.on('change', ...)へ統一しましょう。

テキスト入力でchangeを使う

テキスト入力では、文字を入力しただけではchangeは発火しません。入力後にTabキーで移動するか、入力欄の外をクリックしてフォーカスを外すと発火します。

次の例では、名前を確定すると入力値が結果欄へ表示されます。「入力を確定」ボタンは、あとで説明する.trigger('change')も試せるように用意しています。

テキスト入力のchangeイベントで確定した値を表示した画面

HTMLで入力欄と結果欄を作る

index.htmlを作り、入力欄、確認ボタン、結果を表示する<p>を配置します。jQuery本体を先に、自分のscript.jsを後に読み込んでください。

<!doctype html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>テキスト入力のchangeイベント</title>
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <main class="demo">
      <p class="demo__label">テキスト入力の例</p>
      <h1>入力を確定すると結果が変わります</h1>
      <p class="lead">名前を入力し、Tabキーを押すか入力欄の外をクリックしてください。</p>

      <label for="user-name">お名前</label>
      <input id="user-name" type="text" value="山田 花子" placeholder="例:山田 花子">
      <button id="confirm-button" type="button">入力を確定</button>
      <p id="text-result" class="result" aria-live="polite"></p>
    </main>

    <script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
    <script src="script.js"></script>
  </body>
</html>

labelforと入力欄のidを同じ値にすると、ラベルをクリックして入力欄へ移動できます。aria-live="polite"は、結果の変化を支援技術へ伝える指定です。

changeで入力値を表示する

script.jsでは、.val()で入力値を取得し、.text()で結果欄を更新します。

$('#user-name').on('change', function () {
  const name = $(this).val().trim();
  const message = name
    ? `入力が確定しました:${name}`
    : '名前は未入力です。';

  $('#text-result').text(message);
});

$('#confirm-button').on('click', function () {
  $('#user-name').trigger('change');
});

$('#user-name').trigger('change');

trim()は文字列の前後にある余分な空白を取り除きます。空欄なら「名前は未入力です」と表示するため、入力確認にも利用できます。

セレクトボックスでchangeを使う

<select>は、別の<option>を選んだ時点でchangeが発火します。選択した値に合わせて、プレビューの色と文章を変更してみましょう。

セレクトボックスのchangeイベントでテーマを変更した画面

index.htmlvalueには、JavaScriptで扱いやすい英数字を指定します。画面に表示する日本語とは分けておくと、条件分岐を書きやすくなります。

<main class="demo">
  <p class="demo__label">セレクトボックスの例</p>
  <h1>選択したテーマを表示します</h1>
  <p class="lead">選択肢を変更すると、その場でプレビューが切り替わります。</p>

  <label for="theme-select">表示テーマ</label>
  <select id="theme-select">
    <option value="default">標準</option>
    <option value="ocean" selected>海</option>
    <option value="forest">森</option>
  </select>
  <div id="theme-preview" class="preview"></div>
</main>

script.jsでは、選択値に対応するクラスと文章を設定します。最後の.trigger('change')は、ページ表示時にも選択済みの値を反映するための処理です。

const themeNames = {
  default: '標準',
  ocean: '海',
  forest: '森',
};

$('#theme-select').on('change', function () {
  const theme = $(this).val();

  $('#theme-preview')
    .removeClass('is-ocean is-forest')
    .addClass(theme === 'default' ? '' : `is-${theme}`)
    .text(`現在のテーマ:${themeNames[theme]}`);
}).trigger('change');

radioとcheckboxでchangeを使う

ラジオボタンとチェックボックスは、選択状態を切り替えた時点でchangeが発火します。複数の要素へ同じ処理を設定し、現在の選択内容をまとめて表示できます。

ラジオボタンとチェックボックスのchangeイベントで選択内容を表示した画面

ラジオボタンは同じnameにすると、グループ内で1つだけ選択できます。関連する選択肢はfieldsetlegendでまとめると、内容が伝わりやすくなります。

<main class="demo">
  <p class="demo__label">選択項目の例</p>
  <h1>選択内容をまとめて表示します</h1>

  <fieldset>
    <legend>希望する連絡方法</legend>
    <label class="choice">
      <input type="radio" name="contact" value="メール">メール
    </label>
    <label class="choice">
      <input type="radio" name="contact" value="電話" checked>電話
    </label>
  </fieldset>

  <label class="choice">
    <input id="newsletter" type="checkbox" checked>お知らせを受け取る
  </label>
  <p id="choice-result" class="result" aria-live="polite"></p>
</main>

:checkedを付けると、現在選択されているラジオボタンだけを取得できます。チェックボックスの状態は、.prop('checked')で真偽値として確認します。

function updateChoices() {
  const contact = $('input[name="contact"]:checked').val();
  const newsletter = $('#newsletter').prop('checked')
    ? '受け取る'
    : '受け取らない';

  $('#choice-result').text(
    `連絡方法:${contact}/お知らせ:${newsletter}`
  );
}

$('input[name="contact"], #newsletter').on('change', updateChoices);
updateChoices();

3つの例で共通して使うCSS

実際の表示画像では、次のCSSを共通で使っています。style.cssへ記述すると、フォームと結果欄の見た目を再現できます。

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  padding: 40px 20px;
  color: #162033;
  background: #f2f6fc;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

.demo {
  width: min(760px, 100%);
  margin: 0 auto;
  padding: 36px;
  border: 1px solid #d9e2ef;
  border-radius: 20px;
  background: #fff;
  box-shadow: 0 16px 40px rgb(41 70 115 / 10%);
}

.demo__label {
  margin: 0 0 8px;
  color: #2468d8;
  font-weight: 700;
}

h1 {
  margin: 0 0 12px;
  font-size: clamp(28px, 5vw, 40px);
}

.lead {
  margin: 0 0 28px;
  color: #536079;
}

label,
legend {
  display: block;
  margin-bottom: 10px;
  font-weight: 700;
}

input[type="text"],
select {
  width: 100%;
  padding: 13px 14px;
  border: 2px solid #c8d3e2;
  border-radius: 10px;
  font: inherit;
}

input:focus,
select:focus {
  border-color: #2468d8;
  outline: 3px solid rgb(36 104 216 / 16%);
}

button {
  margin-top: 14px;
  padding: 12px 20px;
  border: 0;
  border-radius: 10px;
  color: #fff;
  background: #2468d8;
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}

.result {
  margin: 22px 0 0;
  padding: 18px;
  border-left: 6px solid #2468d8;
  border-radius: 10px;
  background: #eef5ff;
  font-weight: 700;
}

.preview {
  margin-top: 24px;
  padding: 28px;
  border-radius: 14px;
  background: #f5f7fb;
  text-align: center;
  font-weight: 700;
}

.preview.is-ocean {
  color: #075985;
  background: #e0f2fe;
}

.preview.is-forest {
  color: #166534;
  background: #dcfce7;
}

fieldset {
  margin: 0 0 20px;
  padding: 0;
  border: 0;
}

.choice {
  display: flex;
  gap: 10px;
  align-items: center;
  margin: 0 0 12px;
  padding: 14px;
  border: 1px solid #d9e2ef;
  border-radius: 10px;
}

.choice input {
  width: 20px;
  height: 20px;
}

@media (max-width: 560px) {
  body {
    padding: 20px 12px;
  }

  .demo {
    padding: 24px 18px;
  }
}

changeとinputの違い

テキスト入力で結果をリアルタイムに変えたい場合は、イベント名をinputにします。入力のたびに処理されるため、検索候補、文字数カウント、パスワード条件の表示などに向いています。

$('#search-word').on('input', function () {
  const length = $(this).val().length;
  $('#count').text(`${length}文字入力されています`);
});

入力中に重い通信処理を毎回行うと、画面が遅くなることがあります。確定後に1回だけ処理したい場合はchangeを選びましょう。

JavaScriptで値を変えたときは自動発火しない

.val()で値を変更しても、changeイベントは自動では発火しません。値の変更後に同じ処理を実行したいときは、.trigger('change')を続けて指定します。

// 値は変わるが、changeは発火しない
$('#theme-select').val('forest');

// 値を変えたあと、changeも発火させる
$('#theme-select').val('forest').trigger('change');

.trigger('change')は、初期値を画面へ反映したいときや、別の操作から同じ更新処理を呼びたいときに便利です。

あとから追加した要素にもchangeを設定する

ページ表示後に追加されるフォーム要素は、最初の$('.dynamic-field').on(...)では対象になりません。すでに存在する親要素へイベントを設定する「イベント委譲」を使います。

$('#form-area').on('change', '.dynamic-field', function () {
  console.log($(this).val());
});

#form-areaは、動的要素を含む最も近い固定の親要素にします。すべてをdocumentへ設定するより、関係する範囲を限定したほうが処理を追いやすくなります。

.on()によるイベント設定を詳しく確認したい場合は、次の記事も参考にしてください。

changeが動かないときの確認ポイント

テキスト入力からフォーカスを外していない

テキスト入力では、入力中ではなく値を変更してフォーカスを外したときに発火します。1文字ごとに処理したいならinputイベントへ変更してください。

同じ値を選び直している

changeは値の変更を検知するイベントです。selectで現在と同じ選択肢を選ぶ、テキストを編集して元の値へ戻すなど、最終的な値が変わっていない場合は発火しないことがあります。

セレクタがHTMLと一致していない

$('#theme-select')id="theme-select"を選び、$('.theme-select')class="theme-select"を選びます。#.の取り違えを確認しましょう。

jQueryより先にscript.jsを読み込んでいる

jQuery本体が読み込まれる前に$()を実行すると、$ is not definedになります。HTMLではjQuery本体を先、自分のscript.jsを後に置いてください。

矢印関数でthisを使っている

イベント内で変更された要素をthisとして使う場合は、function () {}を使います。矢印関数のthisはイベント元の要素を指しません。

// thisで変更元を取得できる
$('#target').on('change', function () {
  console.log($(this).val());
});

// 矢印関数ではevent.currentTargetを使う
$('#target').on('change', (event) => {
  console.log($(event.currentTarget).val());
});

jQueryのchangeについてよくある質問

changeで入力中の文字を取得できますか?

値は取得できますが、テキスト入力ではフォーカスを外すまで発火しません。入力中に表示を更新する場合は.on('input', handler)を使います。

複数のinputへまとめて設定できますか?

できます。共通のクラスを付けて$('.form-field').on('change', handler)と指定します。処理内ではthisから実際に変更された要素を取得できます。

changeイベントを解除するにはどうしますか?

.off('change', handler)で解除できます。同じ名前の関数を登録時と解除時に渡せるよう、解除が必要な処理は無名関数ではなく名前付き関数にすると管理しやすくなります。

まとめ

jQueryでフォームの値変更を検知するときは、.on('change', handler)を使います。処理内の$(this).val()で、実際に変更された要素の値を取得できます。

select、radio、checkboxは選択時にすぐ発火しますが、テキスト入力は値を変えてフォーカスを外したときに発火します。入力中に毎回処理する場合はinput、JavaScriptから同じ処理を呼ぶ場合は.trigger('change')を使い分けましょう。