最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - VueJS : Filter array of objects when user search for something - Stack Overflow

programmeradmin2浏览0评论

Basically, this code is responsible to display into a dropdown the list of cars name contained inside the sortedCars array. (This array is sorted by string asc).

Now, I added an input text, and I'm trying to filter automatically the list of cars matching with the entered name value.

With the following code, the UI is never updated. Where is the mistake ?

<template>
        <div class="btn-group pull-left">
            <input type="text" @keyup="onFilterCars" v-model="searchCarTextValue" />
            <a v-for="car in this.sortedCars" :key="car.name" @click="onSelectCategoryFilterLabel" class="dropdown-item" href="#">
                <span v-else>{{ car.name }}</span>
            </a>
        </div>
</template>

<script>
export default {
    data() {
        return {
            inputFilterText: "",
            mapFilteringEnabled: false,
            searchCarTextValue: ""
        };
    },
    props: {
        cars: {
            type: Array
        }
    },
    puted: {

        sortedCars: function() {

            function pare(a, b) {

                if (a.name < b.name)
                    return -1;
                if (a.name > b.name)
                    return 1;

                return 0;
            }

            var sortedArr = this.cars.sort(pare);

            return sortedArr;
        }

    },
    methods: {

        onFilterCars() {
            if (this.searchCarTextValue) {
                var arrayFiltered = this.sortedCars.filter( (car) => {
                    return car.name.toLowerCase().indexOf(this.searchCarTextValue.toLowerCase()) != -1
                });
                this.sortedCars = arrayFiltered;
            }
        }

    }
};
</script>

Basically, this code is responsible to display into a dropdown the list of cars name contained inside the sortedCars array. (This array is sorted by string asc).

Now, I added an input text, and I'm trying to filter automatically the list of cars matching with the entered name value.

With the following code, the UI is never updated. Where is the mistake ?

<template>
        <div class="btn-group pull-left">
            <input type="text" @keyup="onFilterCars" v-model="searchCarTextValue" />
            <a v-for="car in this.sortedCars" :key="car.name" @click="onSelectCategoryFilterLabel" class="dropdown-item" href="#">
                <span v-else>{{ car.name }}</span>
            </a>
        </div>
</template>

<script>
export default {
    data() {
        return {
            inputFilterText: "",
            mapFilteringEnabled: false,
            searchCarTextValue: ""
        };
    },
    props: {
        cars: {
            type: Array
        }
    },
    puted: {

        sortedCars: function() {

            function pare(a, b) {

                if (a.name < b.name)
                    return -1;
                if (a.name > b.name)
                    return 1;

                return 0;
            }

            var sortedArr = this.cars.sort(pare);

            return sortedArr;
        }

    },
    methods: {

        onFilterCars() {
            if (this.searchCarTextValue) {
                var arrayFiltered = this.sortedCars.filter( (car) => {
                    return car.name.toLowerCase().indexOf(this.searchCarTextValue.toLowerCase()) != -1
                });
                this.sortedCars = arrayFiltered;
            }
        }

    }
};
</script>
Share Improve this question edited Dec 19, 2019 at 12:34 wawanopoulos asked Dec 19, 2019 at 12:22 wawanopouloswawanopoulos 9,81435 gold badges117 silver badges174 bronze badges 4
  • one note:this.sortedCars changes every time, so after a while it contains nothing, instead you should save the list of all cars somewhere else and filter from that list without altering it, so effecticvely have two lists one with all cars and one filtered – Nikos M. Commented Dec 19, 2019 at 12:25
  • puted property will automatically repute when its dependent properties change. You dont need the onFilterCars handler at all. – Mat J Commented Dec 19, 2019 at 12:31
  • you have div" twice....not the answer but a problem – depperm Commented Dec 19, 2019 at 12:31
  • and a span v-else without an v-if – depperm Commented Dec 19, 2019 at 12:35
Add a ment  | 

2 Answers 2

Reset to default 3

in vue it is easy to filter, usually i take an approach like this:

<template>
<div>
    <div" class="btn-group pull-left">
        <input type="text" v-model="filters.searchCarTextValue" />
    </div">
</div>
</template>

<script>
export default {
{
    data(){
        return {
            filters:{
                searchCarTextValue: ''
            }
        }
    },
    props: {
        cars: {
            type: Array
        }
    },
    puted: {
        // returns list of cars based of filters
        filtered_cars(){
            let vm = this;
            if(!vm.filters.searchCarTextValue){
                return [];
            }
            return vm.sortedCars.filter(car => {
                return car.name.toLowerCase().indexOf(vm.filters.searchCarTextValue.toLowerCase()) != -1
            })
        },
        sortedCars: function() {

            function pare(a, b) {

                if (a.name < b.name)
                    return -1;
                if (a.name > b.name)
                    return 1;

                return 0;
            }

            var sortedArr = this.cars.sort(pare);

            return sortedArr;
        }
    }
}
</script>

This way there is no need to use a method to filter, since the puted will change whenever filters.searchCarTextValue or sortedCars changes. So you also won't need a button to trigger the filtering.

working example: https://jsfiddle/rmfbpLk9/2/

There was several bugs in the code as people stated in the ments, i've fixed all those, and changed around your method to a puted, and removed all the places where you actually were settings variables and puted declarations wrong.

Working sandbox: https://codesandbox.io/s/musing-feather-10isg

Code:

<template>
  <div>
    <div class="btn-group pull-left">
      <input type="text" v-model="searchCarTextValue">
      <a
        v-for="car in this.filteredCars"
        :key="car.name"
        @click="onSelectCategoryFilterLabel"
        class="dropdown-item"
        href="#"
      >
        <span>{{ car.name }}</span>
      </a>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      inputFilterText: "",
      mapFilteringEnabled: false,
      searchCarTextValue: ""
    };
  },
  props: {
    cars: {
      type: Array
    }
  },
  puted: {
    filteredCars() {
      function pare(a, b) {
        if (a.name < b.name) return -1;
        if (a.name > b.name) return 1;

        return 0;
      }

      let cars = this.cars.filter(car => {
        return (
          car.name
            .toLowerCase()
            .indexOf(this.searchCarTextValue.toLowerCase()) != -1
        );
      });

      cars.sort(pare);

      return cars;
    }
  },
  methods: {
    onSelectCategoryFilterLabel() {
      console.log("OK");
    }
  }
};
</script>
发布评论

评论列表(0)

  1. 暂无评论