【Vuetify3】DataTableでカラム別にFilterしたい

2024-02-27

はじめに

  • Custom filterでは、全てのカラムを対象にフィルタリングされてしまう
  • 代わりにCustom key filterというものを使う必要になるが、このサンプルコードが公式ドキュメントに載っていない。くそったれ

Custom key filter を使った例

<template>
  <v-data-table
    :headers="headers"
    :items="items"
    :search="[nameInput, cvInput].toString()"
    :filter-keys=""
    :custom-key-filter="customKeyFilter"
    filter-mode="every"
  >
    <template v-slot:top>
      <v-text-field v-model="nameInput" label="名前" class="pa-2" />
      <v-text-field v-model="seriesInput" label="シリーズ" class="pa-2" />
      <v-text-field v-model="cvInput" label="CV" class="pa-2" />
    </template>
  </v-data-table>
</template>

<script setup lang="ts">
const nameInput = ref("");
const seriesInput = ref("");
const cvInput = ref("");

const headers = [
  {
    title: "名前",
    align: "start",
    key: "name",
  },
  {
    title: "シリーズ",
    align: "end",
    key: "series",
  },
  {
    title: "CV",
    align: "end",
    key: "cv",
  },
];

const items = [
  {
    name: "キュアエール",
    series: "HUGっと!プリキュア",
    cv: "引坂理絵",
  },
  {
    name: "キュアアンジュ",
    series: "HUGっと!プリキュア",
    cv: "本泉莉奈",
  },
  {
    name: "キュアエトワール",
    series: "HUGっと!プリキュア",
    cv: "小倉唯",
  },
  {
    name: "キュアマシェリ",
    series: "HUGっと!プリキュア",
    cv: "田村奈央",
  },
  {
    name: "キュアアムール",
    series: "HUGっと!プリキュア",
    cv: "田村ゆかり",
  },
];

// フィルター対象とするカラムのキー名を指定する
// NOTE: filterKeysの型は string | string[] のため、as constを使用できない←カスがよ
const filterKeys = ["name", "series", "cv"];

// キーごとにフィルター関数を定義する
const customKeyFilter = {
  name: (value: string, _query: string, _item: unknown) => {
    // 完全一致の文字列比較
    return value === nameInput.value;
  },
  series: (value: string, _query: string, _item: unknown) => {
    // 部分一致
    return value.indexOf(cvInput.value) > -1;
  },
  cv: (value: string, _query: string, _item: unknown) => {
    // これでも部分一致できるらしい(ビビるのでやめてほしい)
    return ~value.indexOf(cvInput.value);
  },
};
</script>

補足

searchPropsは string 型なので、:search="[nameInput, cvInput].toString()"のように、一度配列にぶち込んでからstring型に変換することで解決。ちゃんと入力判定されたのでこれで良いと思う

filter-modePropsはここではeveryを指定しているが、他にもsome, union, intersectionがあるので
その場に応じたものを指定していただければ。
(基本everyと思ってたけどデフォルトintersectionなんだよな)
参考: https://vuetifyjs.com/en/api/v-data-table/#props-filter-mode

ちなみに詳細な型とかは ↓ らへんのソース見れば分かる
https://github.com/vuetifyjs/vuetify/blob/0b7578c337a1cfb668eb7c8c415bfa553d7c9581/packages/vuetify/src/composables/filter.ts#L12-L30

スポンサーリンク