🌊

Quasar framework のテーブルを使用して、一覧を複数項目での絞り込みを実装する方法

2023/03/09に公開

初めに

Quasar Framework のテーブルコンポーネントを使用して表示した一覧を、複数項目での絞り込み機能を実装する時に少し躓いてしまったので、その解決方法をまとめました。

環境

Vue3 / Nuxt3 / Quasar Framework

コード

先に複数項目での絞り込みを実装したコードを記載します。

<script setup lang="ts">
import type { QTableProps } from 'quasar'

const columns: QTableProps['columns'] = [
  { name: 'name', label: '氏名', align: 'left', field: 'name', classes: row => row.gender === '女性' ? 'bg-pink-1' : '' },
  { name: 'gender', label: '性別', align: 'left', field: 'gender', classes: row => row.gender === '女性' ? 'bg-pink-1' : '' },
  { name: 'hobby', label: '趣味', align: 'left', field: 'hobby', classes: row => row.gender === '女性' ? 'bg-pink-1' : '' }
]

const rows = [
  { name: 'テスト 春郎', gender: '男性', hobby: 'サッカー' },
  { name: 'テスト 春子', gender: '女性', hobby: '旅行' },
  { name: 'テスト 夏郎', gender: '男性', hobby: '釣り' },
  { name: 'テスト 夏子', gender: '女性', hobby: '映画鑑賞' },
  { name: 'テスト 秋郎', gender: '男性', hobby: '旅行' }
]

// q-tableのfilterに設定する
const filter = reactive({
  isMale: false,
  isFemale: false,
  searchHobby: '',
})

// データ絞り込み関数 q-tableのfilter-methodに設定する
const filteringData = (rows: readonly any[]) => {
  let retRows = rows

  if (filter.isMale) {
    retRows = retRows.filter(row => row.gender === '男性')
  }

  if (filter.isFemale) {
    retRows = retRows.filter(row => row.gender === '女性')
  }

  if (filter.searchHobby.length > 0) {
    retRows = retRows.filter(row => row.hobby === filter.searchHobby)
  }

  return retRows
}
</script>

<template>
  <q-layout view="hHh lpR fFf">
    <q-page-container>
      <div class="q-pa-md">
        <q-table title="ユーザー一覧" :rows="rows" :columns="columns" :filter="filter" :filter-method="filteringData" row-key="name" color="amber">
          <template v-slot:top-right>
            <div class="row">
              <div class="item-right unworkable-checkbox">
                <q-checkbox v-model="filter.isMale" label="男性" color="secondary" />
              </div>
              <div class="item-right q-mr-lg">
                <q-checkbox v-model="filter.isFemale" label="女性" color="secondary" />
              </div>
            </div>
            <q-input borderless dense debounce="300" v-model="filter.searchHobby" placeholder="趣味">
              <template v-slot:append>
                <q-icon name="search" />
              </template>
            </q-input>
          </template>
        </q-table>
      </div>
    </q-page-container>
  </q-layout>
</template>

画面

絞り込みなし

性別:男性で絞り込み

性別:女性で絞り込み

趣味:旅行で絞り込み

性別:女性&趣味:旅行で絞り込み

絞り込み方法

絞り込みを検知できるよう設定

各絞り込み項目を持つリアクティブなオブジェクトををq-tableタグのfilterに設定する。

// q-tableのfilterに設定する
const filter = reactive({
  isMale: false,
  isFemale: false,
  searchHobby: '',
})

各リアクティブな絞り込み項目を持つオブジェクトを返却するcomputedファンクションを設定してもOKでした。

const isMale = ref(false)
const isFemale = ref(false)
const searchHobby = ref('')

// q-tableのfilterに設定する
const filter = computed(() => {
  return {
    isMale: isMale.value,
    isFemale: isFemale.value,
    searchHobby: searchHobby.value
  }
})

絞り込みを検知した時に実際に絞り込みを行う関数の設定

q-tableタグのfilter-methodに設定する絞り込むファンクションは、第一引数にデータ全件を配列で受け取れるので、この配列を各絞り込み項目の入力内容で絞り込み、その配列を返却するとその配列内容で一覧が更新される。

// データ絞り込み関数 q-tableのfilter-methodに設定する
const filteringData = (rows: readonly any[]) => {
  let retRows = rows

  if (isMale.value) {
    retRows = retRows.filter(row => row.gender === '男性')
  }

  if (isFemale.value) {
    retRows = retRows.filter(row => row.gender === '女性')
  }

  if (searchHobby.value.length > 0) {
    retRows = retRows.filter(row => row.hobby === searchHobby.value)
  }

  return retRows
}

最後に

いかがでしたでしょうか。

最初に実装した時は、Quasar公式のQTable Apiを参考にしたのですが、分からなく少し躓いてしまいました。
最終的にはCodePenのこのコードを参考にして理解できました。

Quasarのテーブルには他にも様々な機能が備わっていて、慣れてしまえば意外と使いやすいのかなと思えるようになりました。

レスキューナウテックブログ

Discussion