LoginSignup
53
38

More than 3 years have passed since last update.

vue.jsのv-modelで複数のチェックボックスの状態を管理したい

Posted at

やりたいこと

チェックボックスがいくつかあって、そのうちどれがチェックされているのかを知りたい。

とりあえず完成版コード

<template>
  <section>
    <div v-for="(poke, i) in pokes" :key="i">
      <input
        :id="'poke' + i"
        type="checkbox"
        :value="poke"
        v-model="selectedPokes"
      >
      <label :for="'poke' + i">{{poke}}</label>
    </div>
  </section>
</template>

<script>
export default {
  data() {
    return {
      pokes: [
        'ピカチュウ', 'カイリュー', 'ヤドラン', 'ピジョン', 'コダック', 'コラッタ', 'ズバット', 'ギャロップ'
      ],
      selectedPokes: []
    }
  }
}
</script>

yc0dw-rc5jb.gif

詳しく

以下のように、チェックボックスひとつにつきv-modelをひとつ使えば実現できることはわかります。

<template>
  <section>
    <input
      id="pika"
      type="checkbox"
      v-model="pika"
    >
    <label for="pika">ピカチュウ</label>

    <input
      id="kai"
      type="checkbox"
      v-model="kai"
    >
    <label for="kai">カイリュー</label>

    <input
      id="yado"
      type="checkbox"
      v-model="yado"
    >
    <label for="yado">ヤドラン</label>
  </section>
</template>

<script>
export default {
  data() {
    return {
      pika: false,
      kai: false,
      yado: false
    }
  }
}
</script>

しかしチェックボックスが100個ある場合そうもいきません。
(ただしチェックボックスが実際に100個になるようなら設計を見直した方がよいです。)
また、リストをAPIなどから引っ張ってきて、チェックボックスがいくつになるか確定出来ない場合なども困ります。

解決方法

  • checkbox要素に:valueを与える
  • v-modelで配列として受け取る。
<div v-for="(poke, i) in pokes" :key="i">
  <input
    :id="'poke' + i"
    type="checkbox"
    :value="poke"
    v-model="selectedPokes"
  >
  <label :for="'poke' + i">{{poke}}</label>
</div>
selectedPokes: []

こうすることで上に貼ったgifのように複数の値を保持することが出来ます。

失敗パターン

v-modelを受け取るdataの初期値を配列にしておかないと失敗します。

selectedPokes: ''

y71zy-0q9et.gif

おしまい

正直なぜこれでいけるのかよくわかっていません。
詳しい方ぜひ教えてください。

なお僕は「クサイハナ」までしか覚えていません。

53
38
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
53
38