Quasar表格列过滤

7

1) 有没有一种实现quasar表格列过滤类似于datatables的方法? https://datatables.net/extensions/fixedheader/examples/options/columnFiltering.html

理想情况下,它应该是一个自动填充文本字段,并过滤表上的所有行。我有一个带有25个列的表格,因此需要一个强大的解决方案。

2) 数据后端过滤部分有任何建议吗?我应该使用筛选器调用数据库还是在客户端存储主列表并进行客户端过滤?


1
在我看来,你应该基于QTable制作自己的组件。你可以通过使用插槽和控件来实现你的目标。 - Maksim Tikhonov
3个回答

2

1
你还可以在现有的 q-table 中的头部插槽中添加 q-inputs,来扩展它。这些输入创建了一个名为 "filter" 的对象,该对象被转换为一个 "filterTerms" 的数组。该数组被内部传递给 q-table 的 "filterMethod",你可以使用它来进行实际的过滤。
你可以在 stackblitz 上查看我的 演示。我相信样式还可以进一步调整。
这只是一个入门。我相信你可以修改代码以自动填充 q-input 字段。至于在客户端/服务器端进行过滤,这取决于你的实际用例。如果有几百行数据,我认为在浏览器中进行过滤没有问题。
// parent.vue
<template>
 <FilterTable dense flat :columns="columns" :rows="rows" />
</template>

// FilterTable.vue
<template>
  <q-table :filterMethod="filterMethod" :filter="filterTerms">
    <template v-slot:header="slotProps">
      <q-tr :props="slotProps">
        <q-th v-for="col in slotProps.cols" :key="col.name" :props="slotProps">
          <q-input v-model.trim="filter[col.name]" @click.stop />
          {{ col.label }}
        </q-th>
      </q-tr>
    </template>
  </q-table>
</template>

<script setup>
import { computed, reactive } from 'vue'

let filter = reactive({})
let filterTerms = computed(() => {
  return getFilterTerms(filter)
})

const getFilterTerms = (filter) => {
  // TODO values are not guaranteed to be in order of property creation
  // see https://dev59.com/Ul0a5IYBdhLWcg3wqaNS
  return Object.entries(filter).map((entry) => {
    return { column: entry[0], value: entry[1] }
  })
}

const filterMethod = (rows, terms) => {
  for (const term of terms) {
    rows = rows.filter((row) => {
      if (('' + row[term.column]).startsWith('' + term.value)) {
        return true
      }

      return false
    })
  }
  return rows
}
</script>


0

可以使用 Lodash 完成。

以下代码使用选择器或文本输入实现筛选。

请注意,这仅适用于客户端。

<template>
  <q-page padding>
      <div class="row q-my-lg">
          <div class="col-3">
          <q-select style="width:250px" filled v-model="dessert" :options="desserts" :label="dessert" stack-label dense @input="filterLocation"></q-select>
          </div>
          <div class="col-2">
            <q-input dense @input="searchByDessert" hint="search by dessert" v-model="dessertName" maxlength="25" ></q-input>
          </div>
      </div>
      <div class="row">
        <div class="col">
          <q-table
            title="Treats"
            :data="data"
            :columns="columns"
            row-key="name"
            :filter="filter"
            :filter-method="filterData"
          ></q-table>
        </div>
      </div>
  </q-page>
</template>

<script>

const lodash = require('lodash')

export default {
  name: 'PageIndex',
  data () {
    return {
      dessert: '',
      desserts: [],
      dessertName: '',
      filter: { value: '' },
      calorie: '',
      columns: [
        {
          name: 'name',
          required: true,
          label: 'Dessert (100g serving)',
          align: 'left',
          field: row => row.name,
          format: val => `${val}`,
          sortable: true
        },
        { name: 'calories', align: 'center', label: 'Calories', field: 'calories', sortable: true },
        { name: 'fat', label: 'Fat (g)', field: 'fat', sortable: true },
        { name: 'carbs', label: 'Carbs (g)', field: 'carbs' },
        { name: 'protein', label: 'Protein (g)', field: 'protein' },
        { name: 'sodium', label: 'Sodium (mg)', field: 'sodium' },
        { name: 'calcium', label: 'Calcium (%)', field: 'calcium', sortable: true, sort: (a, b) => parseInt(a, 10) - parseInt(b, 10) },
        { name: 'iron', label: 'Iron (%)', field: 'iron', sortable: true, sort: (a, b) => parseInt(a, 10) - parseInt(b, 10) }
      ],
      data: [
        {
          name: 'Frozen Yogurt',
          calories: 159,
          fat: 6.0,
          carbs: 24,
          protein: 4.0,
          sodium: 87,
          calcium: '14%',
          iron: '1%'
        },
        {
          name: 'Ice cream sandwich',
          calories: 237,
          fat: 9.0,
          carbs: 37,
          protein: 4.3,
          sodium: 129,
          calcium: '8%',
          iron: '1%'
        },
        {
          name: 'Eclair',
          calories: 262,
          fat: 16.0,
          carbs: 23,
          protein: 6.0,
          sodium: 337,
          calcium: '6%',
          iron: '7%'
        },
        {
          name: 'Cupcake',
          calories: 305,
          fat: 3.7,
          carbs: 67,
          protein: 4.3,
          sodium: 413,
          calcium: '3%',
          iron: '8%'
        },
        {
          name: 'Gingerbread',
          calories: 356,
          fat: 16.0,
          carbs: 49,
          protein: 3.9,
          sodium: 327,
          calcium: '7%',
          iron: '16%'
        },
        {
          name: 'Jelly bean',
          calories: 375,
          fat: 0.0,
          carbs: 94,
          protein: 0.0,
          sodium: 50,
          calcium: '0%',
          iron: '0%'
        },
        {
          name: 'Lollipop',
          calories: 392,
          fat: 0.2,
          carbs: 98,
          protein: 0,
          sodium: 38,
          calcium: '0%',
          iron: '2%'
        },
        {
          name: 'Honeycomb',
          calories: 408,
          fat: 3.2,
          carbs: 87,
          protein: 6.5,
          sodium: 562,
          calcium: '0%',
          iron: '45%'
        },
        {
          name: 'Donut',
          calories: 452,
          fat: 25.0,
          carbs: 51,
          protein: 4.9,
          sodium: 326,
          calcium: '2%',
          iron: '22%'
        },
        {
          name: 'KitKat',
          calories: 518,
          fat: 26.0,
          carbs: 65,
          protein: 7,
          sodium: 54,
          calcium: '12%',
          iron: '6%'
        }
      ],
      database: null
    }
  },
  mounted () {
    this.database = this.data
    const desserts = {}
    this.data.forEach(function (element) {
      desserts[element.name] = 1
    })
    this.desserts = Object.keys(desserts)
  },
  methods: {
    searchByDessert (val) {
      if (val === '') {
        this.data = this.this.database
        return this.data
      }
      const needle = val.toLowerCase()
      this.data = lodash.filter(this.database, function (object) {
        return object.name.toLowerCase().indexOf(needle) > -1
      })
    },
    filterLocation (value) {
      this.data = this.database
      this.filter = { value: value }
    },
    filterData () {
      if (this.data.length > 2 && this.filter.value) {
        return lodash.filter(this.data, function (o) {
          return o.name === this.filter.value
        }.bind(this)
        )
      } else {
        return this.data
      }
    }
  }
}
</script>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接