Vuetify.js 2.2のListコンポーネントについて

# 概要

Listコンポーネントの初歩的な使い方のまとめです。

**環境**

* Windows 10 Professional 1909
* Node.js 12.14.1
* Vue.js 2.6.11
* Vuetify.js 2.2.12

**参考**

* [Quick start - Vuetify.js] (https://vuetifyjs.com/en/getting-started/quick-start)
* [Components] (https://vuetifyjs.com/en/components/api-explorer)
* [Styles - Colors] (https://vuetifyjs.com/en/styles/colors)
* [Material Design Icons] (https://cdn.materialdesignicons.com/4.5.95/)


# [Lists] (https://vuetifyjs.com/en/components/lists)

**基本的な構造パターン**

フラットなリストはv-listの下に1つ以上のv-list-itemを配置します。

```text
v-list
   |
   `--- v-list-item
   `--- v-list-item
   `--- v-list-item
```

v-list-itemを使ったときのリストの構造は下記のようになりますが、必ずしもこれらのコンポーネントを全部使わなくてはならないということではありません。
またリストアイテムをv-list-item以外のコンポーネントで表すこともできます。

```text
v-list-item
   |
   `--- v-list-item-avatar (or v-list-item-icon)
   |
   `--- v-list-content
   |       |
   |       `--- v-list-title
   |       `--- v-list-subtitle
   |
   `--- v-list-item-action
           |
           `--- v-list-item-action-text
```

ネストしたリストを表現するにはv-list-groupでv-list-itemをラップします。
さらにv-list-groupにv-list-groupをネストすることで多階層のリストを表現することもできます。

```text
v-list
   |
   `--- v-list-item
   |
   `--- v-list-group
   |      |
   |      `--- v-list-item
   |      `--- v-list-item
   |
   `--- v-list-group
          |
          `--- v-list-group
          |      |
          |      `--- v-list-item
          |      `--- v-list-item
          |
          `--- v-list-group
                 |
                 `--- v-list-item
                 `--- v-list-item
```

## Props

### VList

* [VList] (https://github.com/vuetifyjs/vuetify/blob/v2.2.12/packages/vuetify/src/components/VList/VList.ts)
* [VSheet] (https://github.com/vuetifyjs/vuetify/blob/v2.2.12/packages/vuetify/src/components/VSheet/VSheet.ts)

```text
VList  ---- VSheet ---- BindsAttrs
                   `--- Colorable
                   `--- Elevatable
                   `--- Measurable
                   `--- Themeable
```

|               |name           |type             |default   |relation                    |src       |
|:--------------|:--------------|:----------------|:---------|:---------------------------|:---------|
|**VList**      |dense          |boolean          |false     |                            |  |
|               |disabled       |boolean          |false     |v-list-item                 |  |
|               |expand         |boolean          |false     |                            |  |
|               |flat           |boolean          |false     |v-list-item                 |  |
|               |nav            |boolean          |false     |v-list-item                 |  |
|               |rounded        |boolean          |false     |v-list-item                 |  |
|               |shaped         |boolean          |false     |v-list-item                 |  |
|               |subheader      |boolean          |false     |                            |  |
|               |three-line     |boolean          |false     |                            |  |
|               |tile           |boolean          |<font color="blue"><strong>true</strong></font> |                            |true  |
|               |two-line       |boolean          |false     |                            |  |
|**VSheet**     |tag            |string           |<font color="blue"><strong>'div'</strong></font> |                            |'div' |
|               |tile           |boolean          |false     |                            | |
|Colorable      |color          |string           |undefined |                            | |
|Elevatable     |elevation      |number or string |undefined |                            | |
|Measurable     |height         |number or string |undefined |                            | |
|               |max-height     |number or string |undefined |                            | |
|               |max-width      |number or string |undefined |                            | |
|               |min-height     |number or string |undefined |                            | |
|               |min-width      |number or string |undefined |                            | |
|               |width          |number or string |undefined |                            | |
|Themeable      |dark           |boolean          |false     |                            |null |
|               |light          |boolean          |false     |                            |null |

### VListItem

* [VListItem] (https://github.com/vuetifyjs/vuetify/blob/v2.2.12/packages/vuetify/src/components/VList/VListItem.ts)

```text
VListItem  ---- Colorable
           `--- Routable
           `--- Themeable
           `--- Groupable
           `--- Toggleable
```

|               |name           |type             |default   |relation                    |src       |
|:--------------|:--------------|:----------------|:---------|:---------------------------|:---------|
|**VListItem**  |*active-class* |string           |          |input-value                 |  |
|               |dense          |boolean          |false     |                            |  |
|               |inactive       |boolean          |false     |                            |  |
|               |*link*         |boolean          |false     |                            |  |
|               |selectable     |boolean          |false     |v-list-item                 |  |
|               |*tag*          |string           |<font color="blue"><strong>'div'</strong></font> |                            |'div'  |
|               |three-line     |boolean          |false     |                            |  |
|               |two-line       |boolean          |false     |                            |  |
|               |value          |any              |undefined |                            |  |
|Colorable      |color          |string           |undefined |                            | |
|Routable       |active-class   |string           |undefined |                            |  |
|               |append         |boolean          |false     |                            |  |
|               |disabled       |boolean          |false     |                            |  |
|               |exact          |boolean          |false     |                            |undefined |
|               |exact-active-class|string        |undefined |exact                       |  |
|               |link           |boolean          |-         |v-list-item                 |  |
|               |href           |string or object |undefined |target, link                |  |
|               |to             |string or object |undefined |link                        |  |
|               |nuxt           |boolean          |false     |nuxt-link                   |  |
|               |replace        |boolean          |false     |                            |  |
|               |ripple         |boolean or object|undefined |v-ripple                    |null  |
|               |tag            |string           |-         |                            |  |
|               |target         |string           |undefined |                            |  |
|Themeable      |dark           |boolean          |false     |                            |null |
|               |light          |boolean          |false     |                            |null |
|Groupable      |active-class   |string           |undefined |                            |  |
|               |disabled       |boolean          |false     |                            |  |
|Toggleable     |input-value    |any              |undefined |                            |  |

* input-value

> Controls the active state of the item. This is typically used to highlight the component
> アイテムのアクティブ状態を制御します。 これは通常、コンポーネントを強調するために使用されます

* value

> The value used when a child of a v-list-item-group.
> v-list-item-groupの子の場合に使用される値。


### VListGroup

* [VListGroup] (https://github.com/vuetifyjs/vuetify/blob/v2.2.12/packages/vuetify/src/components/VList/VListGroup.ts)

```text
VListGroup  ---- BindsAttrs
            `--- Bootable
            `--- Colorable
            `--- Toggleable
```

|               |name           |type             |default   |relation                    |src       |
|:--------------|:--------------|:----------------|:---------|:---------------------------|:---------|
|**VListGroup** |active-class   |string           |undefined |                            |''  |
|               |append-icon    |string           |'$expand' |                            |'$expand' |
|               |*color*        |string           |'primary' |                            |'primary' |
|               |disabled       |boolean          |false     |v-list-item                 |  |
|               |group          |string           |undefined |                            |  |
|               |no-action      |boolean          |false     |                            |  |
|               |prepend-icon   |string           |undefined |v-icon                      |  |
|               |ripple         |boolean or object|<font color="blue"><strong>true</strong></font> |v-ripple                    |true  |
|               |sub-group      |boolean          |false     |                            |  |
|Bootable       |eager          |boolean          |false     |                            |  |
|Colorable      |color          |string           |-         |                            |  |
|Toggleable     |value          |any              |undefined |                            |  |

* value

> Expands / Collapse list group
> リストグループを展開/折りたたみます


### VListItemAvatar

* [VListItemAvatar] (https://github.com/vuetifyjs/vuetify/blob/v2.2.12/packages/vuetify/src/components/VList/VListItemAvatar.ts)
* [VAvatar] (https://github.com/vuetifyjs/vuetify/blob/v2.2.12/packages/vuetify/src/components/VAvatar/VAvatar.ts)

```text
VListItemAvatar ---- VAvatar  ---- Colorable
                              `--- Measurable
```

|               |name           |type             |default   |relation                    |src       |
|:--------------|:--------------|:----------------|:---------|:---------------------------|:---------|
|**VListItemAvatar** |horizontal|boolean          |false     |                            |  |
|               |*size*         |number or string |40        |                            |40  |
|**VAvatar**    |left           |boolean          |false     |                            | |
|               |right          |boolean          |false     |                            | |
|               |size           |number or string |48        |                            |48 |
|               |tile           |boolean          |false     |                            | |
|Colorable      |color          |string           |undefined |                            | |
|Measurable     |height         |number or string |undefined |                            | |
|               |max-height     |number or string |undefined |                            | |
|               |max-width      |number or string |undefined |                            | |
|               |min-height     |number or string |undefined |                            | |
|               |min-width      |number or string |undefined |                            | |
|               |width          |number or string |undefined |                            | |

## 実装例

### テーマ

**dark**

ダークテーマのリストです。1つのリストアイテムを3カラム(アバター、コンテンツ、アクション)で構成しました。

* アバター   -> v-list-item-avatar
* コンテンツ -> v-list-item-content
* アクション -> v-list-item-action

```vue
<v-list dark>
  <v-subheader>Todo List</v-subheader>
  <v-list-item v-for="(item, index) in items" :key="index" link>
    <v-list-item-avatar>
      <v-icon left :color="item.iconColor">{{ item.icon }}</v-icon>
    </v-list-item-avatar>
    <v-list-item-content>
      <v-list-item-title>{{ item.title }}</v-list-item-title>
    </v-list-item-content>
    <v-list-item-action>
      <v-checkbox v-model="item.value"></v-checkbox>
      <v-list-item-action-text>Done</v-list-item-action-text>
    </v-list-item-action>
  </v-list-item>
</v-list>
```

![list-dark.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/57b802f3-106e-9fc1-3f65-073643752836.png)

**light**

ライトテーマのリストです。lightプロパティ以外のソースコードはダークテーマとほぼ同一です。（v-list-item-actionの内部要素の順が違う）
![list-light.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/07446813-b355-beaa-ab41-1d9f3887f7ae.png)

### 行の高さ

リストアイテムのコンテンツが複数行になる場合、`two-line`、`three-line`プロパティで行の高さを変えることができます。

**two-line**

```vue
<v-list two-line>
  <v-subheader>Todo List</v-subheader>
  <v-list-item v-for="(item, index) in items" :key="index" link selectable>
    <v-list-item-avatar left>
      <v-icon :color="item.iconColor">{{ item.icon }}</v-icon>
    </v-list-item-avatar>
    <v-list-item-content>
      <v-list-item-title>{{ item.title }} </v-list-item-title>
      <v-list-item-subtitle>{{ item.subTitle }}</v-list-item-subtitle>
    </v-list-item-content>
    <v-list-item-action>
      <v-list-item-action-text>Done</v-list-item-action-text>
      <v-checkbox v-model="item.value"></v-checkbox>
    </v-list-item-action>
  </v-list-item>
</v-list>
```

![list-two-line.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/a93c4535-0d86-cdab-11a5-0b84bc57598d.png)

**three-line**

```vue
<v-list three-line>
  <v-subheader>Todo List</v-subheader>
  <v-list-item v-for="(item, index) in items" :key="index" link>
    <v-list-item-avatar>
      <v-icon :color="item.iconColor">{{ item.icon }}</v-icon>
    </v-list-item-avatar>
    <v-list-item-content>
      <v-list-item-title>{{ item.title }}</v-list-item-title>
      <v-list-item-subtitle>
        {{ item.subTitle }}
        <div>
          <small>{{ item.description }}</small>
        </div>
      </v-list-item-subtitle>
    </v-list-item-content>
    <v-list-item-action>
      <v-list-item-action-text>Done</v-list-item-action-text>
      <v-checkbox v-model="item.value"></v-checkbox>
    </v-list-item-action>
  </v-list-item>
</v-list>
```

![list-three-line.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/f327713e-637f-925e-c8a1-833ec78186df.png)

### カラー

`color`プロパティでリストの背景色を指定します。
下図は"blue lighten-3"を指定したものです。

```vue
<v-list color="blue lighten-3">
```

![list-color.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/0e8e56ee-6519-acf5-8eef-4f2b58ff3226.png)

### エレベーション

`elevation`プロパティでリストが浮き上がってみえるように表示できます。
下図は`elevation`に15を指定したものです。指定できる数値は0～24になります。

```vue
<v-list elevation="15">
```

![list-elevation.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/c626faa7-fade-fcf5-e9f5-72cd44f950e0.png)

### サブヘッダー

`subheader`プロパティを指定すると上部のパディングが除去されます。v-listコンポーネントを複数繋げて表示する場合に2つ目以降のv-listに指定するという使い方をするようです。

```vue
<v-list subheader>
```

`subheader`プロパティを指定しない状態
![list-subheader-off.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/de74a7a6-5b63-6d26-2c01-cfec2269b8c2.png)

`subheader`プロパティを指定した状態
![list-subheader-on.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/9a9bdc7d-4f64-2f20-de51-745daf90a053.png)

### 形状

`dense`、`flat`、`nav`、`rounded`、`shaped`、`tile`プロパティでアクティブ時のリストアイテムの形状を変えることができます。
なお`flat`はアクティブ時の形状は変わりません。

左から`dense`、`flat`、`nav`を指定したものです。
![list-sharp-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/e63f5797-be56-dccc-7747-1bd86b344b84.png)

左から`rounded`、`shaped`、`tile`を指定したものです。
![list-sharp-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/755c47d4-4182-792d-aac8-060324906ab2.png)

### 無効

`disabled`プロパティを指定するとリストアイテム全体がクリックできなくなります。

```vue
<v-list disabled>
```

### 強調表示

v-list-itemの`active-class`プロパティで、リストアイテムがアクティブな時のCSSクラスを指定できます。
アクティブなときというのは、v-list-itemの`input-value`プロパティがtrueのとき、または

```vue
<v-list-item active-class="blue lighten-4">
```

下図は`active-class`プロパティに"blue lighten-4"を指定、2行目と4行目のアイテムの`input-value`プロパティをtrueにしたときのものです。
![list-active-class.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/d98ebbda-cfab-fc2f-c08c-62f01a3ed6f5.png)

### リンク

#### 疑似的なリンク

v-list-itemに`link`プロパティを指定（若しくは`@click`イベントを設定）すると、リストアイテムは疑似的なリンクとして扱われます。
マウスカーソルを合わせるとカーソルがポインターに変わり、クリックするとリップルのエフェクトが発生します。

```vue
<v-list-item link>
```

```vue
<v-list>
  <v-subheader>Todo List</v-subheader>
  <v-list-item
    v-for="(item, index) in items"
    :key="index"
    :input-value="item.value"
    @click="item.value = !item.value"
  >
    <v-list-item-content>
      <v-list-item-title>{{ item.title }}</v-list-item-title>
    </v-list-item-content>
  </v-list-item>
</v-list>
```

下のgifの左側は`link`プロパティを指定していないもの、右側は`@click`イベントを指定したものです。
`link`プロパティを指定していない方はカーソルがポインターにもならず、クリックしてもリップルは発生しません。
![list-link.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/5f4ab750-dace-bc78-abf3-92022a92b934.gif)

#### リンク

`href`、`to`、`nuxt`プロパティを指定するとリストアイテムはリンクとして扱われ、クリックすると画面遷移（またはアンカーへのジャンプ）が行われます。

```vue

```

**リンクの無効化**

リンクとして扱われているリストアイテムに`inactive`を指定すると、リンクとしての挙動は無効化されます。

```vue
<v-list>
  <v-subheader>Todo List</v-subheader>
  <v-list-item
    v-for="(item, index) in items"
    :key="index"
    :input-value="item.value"
    :href="item.url"
    target="_blank"
    inactive
  >
    <v-list-item-content>
      <v-list-item-title>{{ item.title }}</v-list-item-title>
    </v-list-item-content>
  </v-list-item>
</v-list>
```

`inactive`を指定するとカーソルは変わりませんがリップルは発生します。またリンク先への画面遷移も行われません。
![list-link-inactive.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/edee2005-b74d-93f6-060a-50109ef15ea8.gif)

### サイズ

`width`、`min-width`、`max-width`プロパティでリストの横幅を指定できます。リストアイテムが表示領域に収まらない場合はリストアイテムのコンテンツは省略表示されます。
なお`height`、`min-height`、`max-height`プロパティもあり縦幅を指定できますがリストアイテムが表示領域に収まらない場合ははみ出てしまいます。

```vue
<v-list width="200">
```

下図は`width`に200を指定したときのものです。
![list-size.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/697eb659-d661-9c7e-fbc2-3028e132da48.png)

コンテンツが省略されている状態。
![list-size-ommit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/23b728cc-c4a6-c590-3fe8-ebe05daa9adb.png)

### アイコン

v-list-item-iconとv-iconコンポーネントでアイテムの前後に任意のアイコンを配置できます。
下記のコードの通りアイコンの位置はv-list-item-iconとv-list-item-contentの定義で決まります。

```vue
<v-list-item v-for="(item, index) in items" :key="index" link>
  <v-list-item-icon>
    <v-icon right :color="item.iconColor">{{ item.icon }}</v-icon>
  </v-list-item-icon>
  <v-list-item-content>
    <v-list-item-title>{{ item.title }}</v-list-item-title>
  </v-list-item-content>
</v-list-item>
```

```vue
<v-list-item v-for="(item, index) in items" :key="index" link>
  <v-list-item-content>
    <v-list-item-title>{{ item.title }}</v-list-item-title>
  </v-list-item-content>
  <v-list-item-icon>
    <v-icon right :color="item.iconColor">{{ item.icon }}</v-icon>
  </v-list-item-icon>
</v-list-item>
```

![list-icon.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/49d32d58-4ed3-8f9d-e564-268024fd8c10.png)

### アバター

v-list-item-avatarコンポーネントでアバターを表示させることができます。
デフォルトではアバターは丸く表示されます。
※（アバターの表示には[Pravatar CC0 Avatar placeholders] (https://pravatar.cc/)を利用させて頂きました）

```vue
<v-list>
  <v-subheader>Todo List</v-subheader>
  <v-list-item v-for="(item, index) in items" :key="index">
    <v-list-item-avatar>
      <v-img :src="`https://i.pravatar.cc/180?img=${index + 1}`" size="40"></v-img>
    </v-list-item-avatar>
    <v-list-item-content>
      <v-list-item-title>{{ item.title }}</v-list-item-title>
    </v-list-item-content>
  </v-list-item>
</v-list>
```

![list-avatar.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/5cb488fd-721e-0a78-9082-35e57937399f.png)

`tile`プロパティを指定すると四角く表示されます。

```vue
<v-list-item-avatar tile>
```

![list-avatar-tile.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/c396dbbb-38f6-b246-4ae9-ba617a569985.png)

`horizontal`プロパティを指定すると左寄せになります。

```vue
<v-list-item-avatar horizontal>
```

![list-avatar-horizontal-on.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/b71ae6ce-aeac-6f96-2a97-8ae3da74a713.png)

### 組み合わせ

他のコンポーネントと組み合わせた実装例です。

**v-card**

リストアイテムにv-cardコンポーネントを使った例です。

```vue
<v-list>
  <v-subheader>Todo List</v-subheader>
  <v-list-item v-for="(item, index) in items" :key="index">
    <v-card class="ma-1" outlined flat hover style="overflow-x: auto; width: 600px">
      <div class="d-flex flex-no-wrap justify-space-between">
        <div>
          <v-card-title v-text="item.title"></v-card-title>
          <v-card-subtitle v-text="item.subTitle"></v-card-subtitle>
        </div>
        <v-avatar class="ma-2" size="80" tile>
          <v-img src="https://dummyimage.com/80x80/555555/fff.png"></v-img>
        </v-avatar>
      </div>
    </v-card>
  </v-list-item>
</v-list>
```

![list-card.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/f56d4c11-51bc-b994-e9f8-b7a1698cfb93.png)

**v-divider**

v-list-item間にv-dividerコンポーネントを追加することで境界線を表示することができます。

```vue
<v-list>
  <v-subheader>Todo List</v-subheader>
  <template v-for="(item, index) in items">
    <v-divider :key="`div-${index}`"></v-divider>
    <v-list-item :key="`list-${index}`" link>

      <!-- 省略 -->

    </v-list-item>
  </template>
</v-list>
```

![list-divider.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/b69cb4aa-4994-0cc1-24c1-a0c641d05233.png)

リストアイテムの前にアイコン（アバター）を表示する場合で、コンテンツの下だけに境界線を表示したいときはv-dividerコンポーネントに`inset`プロパティを指定します。

```vue
<v-divider inset :key="`div-${index}`"></v-divider>
```

![list-divider-inset.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/fc30b4a3-e9ce-1415-5c01-0c9e5e3ba151.png)

**v-rating**

リストのアクションにv-ratingコンポーネントを使ってレーティングを表示することができます。

```vue
<v-list>
  <v-subheader>Todo List</v-subheader>
  <template v-for="(item, index) in items">
    <v-divider :key="`div-${index}`"></v-divider>
    <v-list-item :key="`list-${index}`" link>

      <!-- 省略 -->

      <v-list-item-action>
        <v-list-item-action-text>rating</v-list-item-action-text>
        <v-rating small dense :value="item.rating" half-increments length="3"></v-rating>
      </v-list-item-action>
    </v-list-item>
  </template>
</v-list>
```

![list-rating.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/685b3a4e-61c8-fb75-7247-af18a9045dc0.png)

## 実装例 (ネストしたメニュー)

### メニューのインデント

ネストしたメニューをインデントする場合は、`no-action`プロパティを指定します。

```vue
<v-list>
  <v-subheader>Menu</v-subheader>
  <v-list-group v-for="menu in menus" :key="menu.name" :prepend-icon="menu.icon" no-action>
    <template v-slot:activator>
      <v-list-item-content>
        <v-list-item-title>{{ menu.name }}</v-list-item-title>
      </v-list-item-content>
    </template>
    <v-list-item v-for="sub in menu.subMenus" :key="sub.name" link>
      <v-list-item-icon>
        <v-icon>{{ sub.icon }}</v-icon>
      </v-list-item-icon>
      <v-list-item-content>
        <v-list-item-title>{{ sub.name }}</v-list-item-title>
      </v-list-item-content>
    </v-list-item>
  </v-list-group>
</v-list>
```

下図の左側が`no-action`プロパティ無し、右側がプロパティ有りです。
![list-group-no-action.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/fcbfc07f-9f24-46d1-5574-8bf4d3126f08.png)

### メニューの開閉

リストに複数のネストしたメニューがある場合、デフォルトではネストしたメニューが開けるのはどれか1つだけですが、`expand`プロパティを指定すると全て開いた状態にできます。

```vue
<v-list expand>
```

下のgifの左側が`expand`プロパティ無し、右側がプロパティ有りです。
![list-group-expand.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/1c98213f-8fc3-43bc-c1bc-47d3818d9596.gif)

### グループ

リストをページのナビゲーションメニューとして使用する場合などで、開いたページに対応するメニューを自動的に開いた状態にするには、`group`プロパティでURLをグルーピングします。

たとえば（コードはだいぶ省略していますが）下記のような3つのメニュー(Group-A, Group-B, Group-C)と、それぞれにページ遷移するメニューがあった場合、開いたページのURLが`/group/b/1`だった場合、Group-Bのメニューが開いた状態になります。

```vue
<v-list>
  <v-subheader>Menu</v-subheader>
  <!-- Group Aのメニュー -->
  <v-list-group group="/group/a">
    <v-list-item to="/group/a/1">
      <v-list-item-title>to A1 page</v-list-item-title>
    </v-list-item>
    <v-list-item to="/group/a/2">
      <v-list-item-title>to A2 page</v-list-item-title>
    </v-list-item>
  </v-list-group>

  <!-- Group Bのメニュー -->
  <v-list-group group="/group/b">
    <v-list-item to="/group/b/1">
      <v-list-item-title>to B1 page</v-list-item-title>
    </v-list-item>
    <v-list-item to="/group/b/2">
      <v-list-item-title>to B2 page</v-list-item-title>
    </v-list-item>
  </v-list-group>

  <!-- Group Cのメニュー -->
  <v-list-group group="/group/c">
    <v-list-item to="/group/c/1">
      <v-list-item-title>to C1 page</v-list-item-title>
    </v-list-item>
    <v-list-item to="/group/c/2">
      <v-list-item-title>to C2 page</v-list-item-title>
    </v-list-item>
  </v-list-group>
</v-list>
```

### 開閉状態のバインド

リストの開閉状態をモデルにバインドすることで状態を永続化できます。
状態は`value`プロパティに指定し、trueであれば開いた状態、falseであれば閉じた状態になります。

```vue
<v-list>
  <v-subheader>Menu</v-subheader>
  <v-list-group
    v-for="menu in menus"
    :key="menu.name"
    :prepend-icon="menu.icon"
    :value="menu.open"
    no-action
    >

    <!-- 省略 -->

  </v-list-group>
</v-list>
```

### 開閉アイコン

リストの開閉状態を示すアイコンは`append-icon`プロパティで指定できます。指定したアイコンは開閉に合わせて上下反転します。

```vue
<v-list-group append-icon="mdi-details">
```

![list-group-icon.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/11bc94fd-8a3e-b698-ffaf-0f72c41777bc.gif)

### 多階層のリスト

リストが多階層ネストする場合、ネストした側のv-list-groupに`sub-group`プロパティを指定する必要があります。

```vue
<v-list>
  <v-subheader>Menu</v-subheader>
  <!-- 1層目のリストグループ -->
  <v-list-group v-for="menu in menus" :key="menu.name" :prepend-icon="menu.icon" no-action>
    <template v-slot:activator>
      <v-list-item-content>
        <v-list-item-title>{{ menu.name }}</v-list-item-title>
      </v-list-item-content>
    </template>
    <template v-for="sub in menu.subMenus">
      <!-- 2層目がリストグループの場合 -->
      <v-list-group v-if="sub.subMenus" :key="sub.name" no-action sub-group>
        <template v-slot:activator>
          <v-list-item-icon class="mr-8">
            <v-icon>{{ sub.icon }}</v-icon>
          </v-list-item-icon>
          <v-list-item-content>
            <v-list-item-title>{{ sub.name }}</v-list-item-title>
          </v-list-item-content>
        </template>
        <!-- 3層目のリスト -->
        <v-list-item v-for="sub2 in sub.subMenus" :key="sub2.name" :to="sub2.url">

          <!-- 省略 -->

        </v-list-item>
      </v-list-group>

      <!-- 2層目が通常のリストの場合 -->
      <v-list-item v-else :key="sub.name" :to="sub.url">

        <!-- 省略 -->

      </v-list-item>
    </template>
  </v-list-group>
</v-list>
```

下のgifでは『Group-A』→『Sub Menu - A_1』と開いています。3層目のメニューのネストが少し浅いので2層目と見分けにくいので、アイコンを右側に表示するなどしたほうがいいかもしれません。
![list-group-sub-group.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/f1ef40d2-b02c-0417-7fee-8dc2962ec12c.gif)


# [List item groups] (https://vuetifyjs.com/en/components/list-item-groups)

リストアイテムにモデルをバインドしてチェックリストのような使い方をすることが簡単にできます。

**基本的な構造パターン**

v-list-item-groupでグループ化するv-list-itemをラップするのが基本的な構造になります。

```text
v-list
   |
   `--- v-list-item-group
          |
          `--- v-list-item
          `--- v-list-item
          `--- v-list-item
```

## Props

### VListItemGroup

* [VListItemGroup] (https://github.com/vuetifyjs/vuetify/blob/v2.2.12/packages/vuetify/src/components/VList/VListItemGroup.ts)
* [VItemGroup] (https://github.com/vuetifyjs/vuetify/blob/v2.2.12/packages/vuetify/src/components/VItemGroup/VItemGroup.ts)

```text
VListItemGroup ---- VItemGroup ---- Proxyable
               |               `--- Themeable
               |
               `--- Colorable 
```

|               |name           |type             |default   |relation                    |src       |
|:--------------|:--------------|:----------------|:---------|:---------------------------|:---------|
|**VListItemGroup**|            |                 |          |                            |  |
|**VItemGroup** |active-class   |string           |'v-item--active'|                      |'v-item--active'  |
|               |mandatory      |boolean          |false     |                            |  |
|               |max            |number or string |undefined |                            |null  |
|               |multiple       |boolean          |false     |                            |  |
|Proxyable      |value          |any              |undefined |                            |  |
|Themeable      |dark           |boolean          |false     |                            |null |
|               |light          |boolean          |false     |                            |null |
|Colorable      |color          |string           |undefined |                            | |


## 実装例

### 単一選択

デフォルトではリストアイテムグループは単一値のモデルにバインドします。つまりラジオボタングループのように振るいまいます。
ただしラジオボタンと違って選択しないこともできるので、選択済みをもう一度クリックすると選択状態が外れます。

```vue
<v-list>
  <v-subheader>Todo List</v-subheader>
  <v-list-item-group v-model="model1">
    <v-list-item v-for="(item, index) in items" :key="index" link :value="item.value">
      <template v-slot:default="{ active, toggle }">
        <v-list-item-avatar>
          <v-icon left color="blue">{{ item.icon }}</v-icon>
        </v-list-item-avatar>
        <v-list-item-content>
          <v-list-item-title>{{ item.title }}</v-list-item-title>
        </v-list-item-content>
        <v-list-item-action>
          <v-list-item-action-text>done</v-list-item-action-text>
          <v-checkbox :input-value="active" @click="toggle"></v-checkbox>
        </v-list-item-action>
      </template>
    </v-list-item>
  </v-list-item-group>
</v-list>
```

```js
<script>
export default {
  data() {
    return {
      model1: 'A',
      model2: 'B',
      model3: ['C'],
      model4: ['D'],
      items: [
        // 省略
      ]
  }
}
</script>
```

![list-item-group-default.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/e6508e2d-869f-6da7-4a36-dada74061530.gif)

### 単一の必須選択

`mandatory`プロパティを指定して必ずどれか選択されている状態にすることができます。（選択済みのリストアイテムをクリックしても選択状態が解除されない）

```vue
<v-list-item-group v-model="model2" mandatory>
```

![list-item-group-mandatory.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/678fd0e3-2464-ba6f-76ed-453332edcb91.gif)

### 複数選択

`multiple`プロパティを指定すると複数選択することができます。この場合バインドするモデルは配列である必要があります。

```vue
<v-list-item-group v-model="model3" multiple>
```

![list-item-group-multiple.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/bfc03767-a5ce-1612-3153-d4d5d3cc6bbf.gif)

### 複数選択（上限付き）

`multiple`に加え`max`プロパティで選択できる上限を指定できます。上限に達している場合未選択のリストをクリックしても選択状態になりません。

```vue
<v-list-item-group v-model="model4" multiple max="3">
```

![list-item-group-multiple-max.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/a7a5051a-810c-1617-ec14-5819668ae034.gif)