【Vue3】checkbox（チェックボックス） 〜 全選択・全解除 〜

チェックボックスを一括で選択・解除するボタンを実装したい時の
Vue.js（Vue3 / Composition API）での記述方法をご紹介します。

# チェックボックスの全選択・全解除

こんな感じで動きます。
![checkbox_allselect_deselect.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3472703/62bc4425-cc92-1e7e-2d7f-1a00678ea297.gif)


### コード完成版
```vuejs:CheckBox.vue
<script setup>
import { ref } from 'vue'

// 補足1参照
const selectedOptions = ref([])

// 選択肢の定数は別ファイルに切り出すことをお勧めしますが、ここでは同じファイル内に記述します
const options = [
  { id: 1, value: '選択肢1' },
  { id: 2, value: '選択肢2' },
  { id: 3, value: '選択肢3' },
  { id: 4, value: '選択肢4' },
]

// 補足2参照
const onSelectAll = () => {
  selectedOptions.value = options.map(option => option.id)
}

// 補足3参照
const onDeselectAll = () => {
  selectedOptions.value = []
}

</script>

<template>
  <div class="margin">
    <label> 選択項目 </label>
    <div class="flex">
      <!-- 補足4参照 -->
      <button
        type="button"
        class="button"
        @click="onSelectAll()">
        全選択
      </button>
      <!-- 補足5参照 -->
      <button
        type="button"
        class="button"
        @click="onDeselectAll()">
        全解除
      </button>
    </div>
    <!-- 補足6参照 -->
    <div
      class="flex"
      v-for="option in options"
      :key="option.id">
      <!-- 補足7参照 -->
      <label
        :for="`selected_${option.id}`">
      <input
        v-model="selectedOptions"
        :id="`selected_${option.id}`"
        type="checkbox"
        :value="option.id" />
        {{ option.value }}
      </label>
    </div>
  </div>
</template>

<style>
/* cssは別ファイルからの読み込みを推奨しますが、ここでは同じファイル内に記述します */
.margin {
  margin: 2em;
}
.flex {
  display: flex;
  gap: 10px;
  margin: 5px 0;
}
.button {
  border: solid 1px #333;
  border-radius: 10%;
  padding: 2px 5px;
}
</style>

```
***

### 各セクションの補足説明です。
#### - scriptタグ内 -

```javascript:補足1
import { ref } from 'vue'

const selectedOptions = ref([])
```
チェックボックスで選択された値を格納する配列"selectedOptions"を
リアクティブ（値が更新された時に変更が検知される状態）にするため、
ref関数を使用しています。

- 参考
  - [リアクティビティーの基礎](https://ja.vuejs.org/guide/essentials/reactivity-fundamentals)
***

```javascript:補足2
const onSelectAll = () => {
  selectedOptions.value = options.map(option => option.id)
}
```

全選択の関数です。
mapメソッドでoptions（選択肢の配列）のidプロパティだけを抽出した新しい配列を
selectedOptionsに代入しています。
scriptタグ内でrefは「.value」でアクセスすることが可能です。

- 参考
  - [【JavaScript】 mapメソッドについて徹底解説！](https://pikawaka.com/javascript/map)
  - [【Vue】refを使ってリアクティブなデータを扱う](https://qiita.com/yusuke1209kitamura/items/a1a24361b33691dd1818)
***

```javascript:補足3
const onDeselectAll = () => {
  selectedOptions.value = []
}
```

全解除の関数です。
selectedOptionsに空配列を代入することで選択した値を全解除しています。
***

#### - templateタグ内 -
```vuejs:補足4
<button
  type="button"
  class="button"
  @click="onSelectAll()">
  全選択
</button>
```
「全選択」ボタンのクリックイベントでonSelectAll関数（全選択の関数）を実行しています。
***

```vuejs:補足5
<button
  type="button"
  class="button"
  @click="onDeselectAll()">
  全解除
</button>
```
「全解除」ボタンのクリックイベントでonDeselectAll関数（全解除の関数）を実行しています。
***

```vuejs:補足6
<div
class="flex"
v-for="option in options"
:key="option.id">
```
v-forを使って、options（選択肢の配列）からデータを取り出し、繰り返しで表示します。

- 参考
  - [リストレンダリング](https://ja.vuejs.org/guide/essentials/list)
  - [v-forの使い方を分かりやすく解説](https://jp.skilled.yashio-corp.com/media/vue/6120/)
***

```vuejs:補足7
<label
  :for="`selected_${option.id}`">
<input
  v-model="selectedOptions"
  :id="`selected_${option.id}`"
  type="checkbox"
  :value="option.id" />
  {{ option.value }}
</label>
```
input要素にv-modelを利用することで、入力値とデータを同期することができます。
チェックした順にvalue属性の値が配列"selectedOptions"に追加されていきます。

- 参考
  - [フォーム入力バインディング](https://ja.vuejs.org/guide/essentials/forms)

<br>
そして、label要素とinput要素を明示的に関連付けるために、
input要素にid属性を、label要素にfor属性を追加しています。
（forとidの値は同じにします）

または、inputをlabelの入れ子にすることでも、関連づけることが可能です。
その場合、forおよびid属性は必要ありません。
（上記ではforおよびidを追加していますが、追加しなくても同じく動作します）

label要素とinput要素を関連付けることで、チェックボックス部分だけでなく、
関連するラベル（テキスト）部分をクリックしてもチェックが入るようになります。

- 参考
  - [\<label>: ラベル要素](https://developer.mozilla.org/ja/docs/Web/HTML/Element/label)
***

以上です！
読んでいただきありがとうございました^^


# 参考記事

https://www.ithands.dev/checkbox-for-vue/#vuejscheckbox