【问题标题】:How do I use "custom filter" prop in data tables in vuetify? or How do I create a custom filter to filter by headers?如何在 vuetify 的数据表中使用“自定义过滤器”道具?或如何创建自定义过滤器以按标题过滤?
【发布时间】:2018-01-22 03:39:07
【问题描述】:

截至发稿之日,我找不到在数据表中使用“自定义过滤器”道具的任何文档。

我只想创建一个自定义过滤器来按标题过滤我的数据表。 我有一个下拉列表,当用户单击下拉列表的选项之一时,它会过滤列表中的一个特定标题。

示例: 下拉选项: 食物类型:水果、肉类、蔬菜

  1. Bakchoi(蔬菜)
  2. 猪肉(肉)
  3. 鸡大腿(肉)
  4. 西瓜(水果)

如果我选择下拉菜单作为肉,它应该只显示猪肉和鸡腿。

【问题讨论】:

  • 你发现了吗?我正在寻找相同的信息。
  • 嘿 Sterling,抱歉回复晚了。在我有机会解决它之前,我就被撤职了。所以我不能说我找到了解决方案,但我相信下面的答案之一应该能够帮助你。 :)

标签: vue.js frontend vuetify.js


【解决方案1】:

就我而言,我有两种不同的过滤方式,即搜索栏和下拉菜单。我尝试对它们都使用custom-filter,但它不起作用,所以我想出了另一种方法

<v-text-field v-model="search" label="Label"></v-text-field>
<v-select
    v-model="select"
    :items="food"
    item-text="type"
    item-value="type"
    :label="Types"
    @change="filterFoodUsingDropDown"
>
</v-select>
<v-data-table
    :search="search"
    :headers="headers"
    :items="food"
    :custom-filter="filterFoodUsingSearchbar"
>
data() {
    return {
        food: [
            { name: 'Bakchoi', type: 'vegetable', calories: 100 },
            { name: 'Pork', type: 'meat', calories: 200 },
            { name: 'Chicken Thigh', type: 'meat', calories: 300 },
            { name: 'Watermelon', type: 'fruit', calories: 10 },
        ],
        headers: [
            { text: 'Name', align: 'left', value: 'name' },
            { text: 'Food Type', align: 'left', value: 'type' },
            { text: 'Calories', align: 'left', value: 'calories' },
        ],
        search: '',
        select: '',
    };
},
methods: {
    filterFoodUsingSearchbar(items, search, filter) {
            // Condition
    }
        
    filterFoodUsingDropDown() {
        if (this.select !== '') {
            // In this case I use vuex to store the original data of the 
               food so that all the data is still exist even we filtered it out
            this.food = this.$store.state.food.filter((item) => item.type === this.select)
        }
    }

【讨论】:

    【解决方案2】:

    看Github上的代码1,貌似customFilter prop是用来覆盖默认方法,用来判断filter prop是如何应用到表中的项目上的.

    默认的customFilter 方法将filter 函数应用于每个项目对象的每个属性名称,并过滤掉任何不包含通过过滤器的属性名称的项目:

    customFilter: {
      type: Function,
      default: (items, search, filter) => {
        search = search.toString().toLowerCase()
        return items.filter(i => (
          Object.keys(i).some(j => filter(i[j], search))
        ))
      }
    },
    

    如果您想阻止任何列包含在过滤器中,或者如果您一直希望阻止过滤掉特定行,则可能需要覆盖此函数。

    您会注意到该方法还依赖于 search 属性,它必须是一个字符串。


    说了这么多,你真的不需要使用那个道具来做你想做的事。您应该只创建一个计算属性来根据您的下拉值过滤项目,并将该计算属性作为items 属性传递。

    这是一个例子:

    new Vue({
      el: '#app',
      data() {
        return {
          food: [
            { name: 'Bakchoi', type: 'vegetable', calories: 100 },
            { name: 'Pork', type: 'meat', calories: 200 },
            { name: 'Chicken Thigh', type: 'meat', calories: 300 },
            { name: 'Watermelon', type: 'fruit', calories: 10 },
          ],
          headers: [
            { text: 'Name', align: 'left', value: 'name' },
            { text: 'Food Type', align: 'left', value: 'type' }, 
            { text: 'Calories', align: 'left', value: 'calories' },
          ],
          foodType: null,
        };
      },
      computed: {
        filteredItems() {
          return this.food.filter((i) => {
            return !this.foodType || (i.type === this.foodType);
          })
        }
      }
    })
    <script src="https://unpkg.com/vue@2.4.2/dist/vue.js"></script>
    <script src="https://unpkg.com/vuetify@0.15.2/dist/vuetify.js"></script>
    <link rel="stylesheet" href="https://unpkg.com/vuetify@0.15.2/dist/vuetify.min.css">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons">
    
    <div id="app">
      <v-app>  
        <v-select 
          label="Food Type" 
          :items="['vegetable', 'meat', 'fruit']"
          v-model="foodType"
        ></v-select>
        
        <v-data-table 
          :headers="headers"
          :items="filteredItems"
          hide-actions
        >
          <template slot="items" scope="{ item }">
            <td>{{ item.name }}</td>
            <td>{{ item.type }}</td>
            <td>{{ item.calories }}</td>
          </template>
        </v-data-table>
      </v-app>
    </div>

    1. 这个答案是在 Vuetify 在 v0.15.2 时编写的。 The source code for the VDataTable component at that version can be found here

    【讨论】:

    • 使用自定义计算属性与自定义过滤器的行为略有不同。如果您使用自定义计算属性并且没有结果,则数据表将显示无数据槽。如果您使用自定义过滤器并且没有结果,则数据表将显示无结果槽。差异通常很重要。
    • @KJohnson 您可以通过使用 no-data 插槽并根据缺少数据是来自源还是计算属性的过滤器来自定义消息来解决差异。
    • 源链接已损坏
    【解决方案3】:

    您也可以像这样使用 customFilter 方法,我已将搜索限制为类型字段。

    new Vue({
        el: '#app',
        data() {
            return {
                food: [
                    { name: 'Bakchoi', type: 'vegetable', calories: 100 },
                    { name: 'Pork', type: 'meat', calories: 200 },
                    { name: 'Chicken Thigh', type: 'meat', calories: 300 },
                    { name: 'Watermelon', type: 'fruit', calories: 10 },
                ],
                headers: [
                    { text: 'Name', align: 'left', value: 'name' },
                    { text: 'Food Type', align: 'left', value: 'type' },
                    { text: 'Calories', align: 'left', value: 'calories' },
                ],
                search: '',
    
            };
        },
        methods: {
            customFilter(items, search, filter) {
    
                search = search.toString().toLowerCase()
                return items.filter(row => filter(row["type"], search));
    
            }
        }
    })
    <script src="https://unpkg.com/vue@2.4.2/dist/vue.js"></script>
    <script src="https://unpkg.com/vuetify@0.15.2/dist/vuetify.js"></script>
    <link rel="stylesheet" href="https://unpkg.com/vuetify@0.15.2/dist/vuetify.min.css">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Material+Icons">
    
    <div id="app">
        <v-app>
            <v-select
                    label="Food Type"
                    :items="['vegetable', 'meat', 'fruit']"
                    v-model="search"
            ></v-select>
    
            <v-data-table
                    :headers="headers"
                    :items="food"
                    :search="search"
                    :custom-filter="customFilter"
                    hide-actions
            >
                <template slot="items" scope="{ item }">
                    <td>{{ item.name }}</td>
                    <td>{{ item.type }}</td>
                    <td>{{ item.calories }}</td>
                </template>
            </v-data-table>
        </v-app>
    </div>

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-04
    • 2011-01-06
    • 1970-01-01
    • 2018-03-17
    • 2020-04-28
    • 1970-01-01
    • 2014-12-01
    相关资源
    最近更新 更多