admin管理员组

文章数量:1387334

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>

本文标签: javascriptVueJSFilter array of objects when user search for somethingStack Overflow