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 theonFilterCars
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 anv-if
– depperm Commented Dec 19, 2019 at 12:35
2 Answers
Reset to default 3in 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>