如何在两个属性上使用 Vue/Vuetify 自动完成过滤器?

Posted

技术标签:

【中文标题】如何在两个属性上使用 Vue/Vuetify 自动完成过滤器?【英文标题】:How to have Vue/Vuetify Autocomplete filter on two properties? 【发布时间】:2019-06-30 21:31:16 【问题描述】:

背景

所以我有一个 vuetify 自动完成输入,用于搜索零件表。零件表有一个标识列、零件编号列、修订列、描述列和其他一些信息列。

我让它工作了,所以自动完成选项会显示部件号、版本和描述,同时在文本字段中输入时会按部件号过滤部件。

问题

但我的目标是能够同时过滤部件号和描述。

我尝试修改 item-text="fpartno" 但不知道如何让它与两个或多个属性一起使用。而且我在网上找到的大多数解决方案只影响选项的显示方式,而不影响它们的过滤方式。

同样删除 item-text 也不起作用。

代码

我将自动完成功能放入单页组件中。我目前正在使用 Typescript,但我也会接受使用 javascript 的答案。如果我可以使用理想的模板语法。

注意:属性fcomment包含描述以防任何人感到困惑。

<template>
    <v-container fluid grid-list-xl>
        <v-layout wrap align-center>
            <v-flex xs12 sm6 d-flex>
                <v-autocomplete :items="inmastxs"
                                label="Part #"
                                item-value="identity_column"
                                item-text="fpartno"
                                cache-items
                                :search-input.sync="search"
                                solo>
                    <template slot="selection" slot-scope="data">
                         data.item.fpartno  -  data.item.frev  ( data.item.fcomment )
                    </template>
                    <template slot="item" slot-scope="data">
                         data.item.fpartno  -  data.item.frev  ( data.item.fcomment )
                    </template>

                </v-autocomplete>
            </v-flex>
        </v-layout>
    </v-container>
</template>

<script lang="ts">

    import Vue from 'vue'
    import  Component, Prop, Watch  from 'vue-property-decorator';
    import  inmastx  from '../../models/M2M/inmastx';
    import axios from 'axios';

    @Component()
    export default class InMastxSearch extends Vue 
        private search: string = "";
        private PartNumber: string = "";
        private loading: boolean = false;
        private inmastxs: inmastx[] = [];

        @Watch('search')
        onPropertyChanged(value: string, oldValue: string) 
            this.fetchParts(value);
        


        private mounted() 
            this.fetchParts("");
        

        private fetchParts(value: string) 
            if (value == null) 
                value = "";
            

            console.log(value);
            this.loading = true
            axios.get("../odata/inmastx?$orderby=fpartno,frev&$top=10&$filter=contains(fpartno,'" + value + "') or contains(fcomment,'" + value + "')")
                .then((response) => 
                    this.inmastxs = response.data.value;
                    console.log(this.inmastxs);
                )
                .catch(function (error) 
                    console.log(error);
                ).then(() => 
                    this.loading = false;
                );
        
    
</script>

如果您需要更多详细信息,请告诉我,并提前致谢。

【问题讨论】:

【参考方案1】:

在这里玩到很晚,但解决方案是绑定自定义过滤器

<v-autocomplete
  :filter="filterObject"
>

然后定义行为

  methods: 
    filterObject(item, queryText, itemText) 
      return (
        item.prop1.toLocaleLowerCase().indexOf(queryText.toLocaleLowerCase()) >
          -1 ||
        item.prop2.toLocaleLowerCase().indexOf(queryText.toLocaleLowerCase()) > -1
      );
    
  

v-autocomplete filter prop documentation 提供指向default ts implementation 的链接。

【讨论】:

当我应用该方法时,它会抛出错误TypeError: Cannot read property 'toLocaleLowerCase' of undefined 检查您在本例中的“项目”是否包含已定义的属性(例如 prop1: "hello", prop2: "world" )以及 queryText 是否为字符串。【参考方案2】:

所以我意识到我使用了错误的工具来完成这项工作。在阅读文档时,我一定错过了关于 Combobox 的部分,其中包含我需要的一切。

无论如何,将 v-autocomplete 更改为 v-combobox 删除 item-text="fpartno" 并添加自定义过滤器给了我的组件我需要的功能。

这里它工作正常:

下面是我更新的代码:

<template>
    <v-container fluid grid-list-xl>
        <v-layout wrap align-center>
            <v-flex xs12 sm6 d-flex>
                <v-combobox :items="inmastxs"
                                label="Part #"
                                item-value="identity_column"
                                :filter="PartRevDescFilter"
                                cache-items
                                :search-input.sync="search"
                                solo>
                    <template slot="selection" slot-scope="data">
                         data.item.fpartno  -  data.item.frev  ( data.item.fcomment )
                    </template>
                    <template slot="item" slot-scope="data">
                         data.item.fpartno  -  data.item.frev  ( data.item.fcomment )
                    </template>    
                </v-combobox>
            </v-flex>
        </v-layout>
    </v-container>
</template>

<script lang="ts">

    import Vue from 'vue'
    import  Component, Prop, Watch  from 'vue-property-decorator';
    import  inmastx  from '../../models/M2M/inmastx';
    import axios from 'axios';

    @Component()
    export default class InMastxSearch extends Vue 
        private search: string = "";
        private PartNumber: string = "";
        private loading: boolean = false;
        private inmastxs: inmastx[] = [];

        @Watch('search')
        onPropertyChanged(value: string, oldValue: string) 
            this.fetchParts(value);
            

        private mounted() 
            this.fetchParts("");
        

        private fetchParts(value: string) 
            if (value == null) 
                value = "";
            
            this.loading = true
            axios.get("../odata/inmastx?$orderby=fpartno,frev&$top=10&$filter=contains(fpartno,'" + value + "') or contains(fcomment,'" + value + "')")
                .then((response) => 
                    this.inmastxs = response.data.value;
                )
                .catch(function (error) 
                    console.log(error);
                ).then(() => 
                    this.loading = false;
                );
        

        private PartRevDescFilter(item: inmastx, queryText, itemText)          
            return (item.fpartno.toLowerCase().includes(queryText.toLowerCase()) || item.frev.toLowerCase().includes(queryText.toLowerCase()) || item.fcomment.toLowerCase().includes(queryText.toLowerCase()));
        
    
</script>

因为问题的标题提到了自动完成而不是组合框,所以我认为这个答案不足以被认为是最佳答案。除非自动完成一直是错误的工具。

【讨论】:

【参考方案3】:

带走:

item-text="fpartno"

并使用:

no-filter="true"

【讨论】:

以上是关于如何在两个属性上使用 Vue/Vuetify 自动完成过滤器?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Laravel 的其他 Vue/Vuetify 组件中嵌入 Vue/Vuetify 组件?

Vue, Vuetify 2, v-data-table - 如何在表格底部显示总原始数据

Vue / Vuetify:获取 v-flex 的尺寸

Vue / Vuetify - 如何对每个芯片项而不是整个选择输入进行验证

如何访问深层嵌套父级中的方法 [Vue][Vuetify]

如何通过单击 v-list 项 vue + vuetify 来选择 v-radio