I have been trying to solve this problem for more than a week, but finally I am forced to ask for help.
I am just implementing a search filter in Vue 2, using Vuetify, but something is going wrong
This is how the search filter looks:
<v-text-field v-model="search" label="Look for name..."></v-text-field>
I have a variable called search in the component data that is two-binding with the text-field v-model
Secondly, I have an array of items:
items: [
{
default: true,
name: 'Text 1',
},
{
default: false,
name: 'Text 2',
},
{
default: false,
name: 'Text 3',
},
{
default: false,
name: 'Text 4',
},
],
I render the list in a div using v-for
<div v-for="(item, index) in filteredItems">
<div style="display: flex">
<input
type="radio"
:checked="item.default"
@click="changeDefault(item, index)"
/>
<h1>{{ item.name }}</h1>
</div>
</div>
This is how the component looks: List and search filter rendered
How the filter works? Here is the code
filteredItems() {
if (this.search) {
return this.items.filter((item) => {
return item.name.toLowerCase().match(this.search);
});
} else {
return this.items;
}
},
As you can see in the rendered list, items have a radio button which can be selected. When some of them are clicked, we call a function called changeDefault whose code is this (just get the default true item and set it to false, and the new one to true)
changeDefault(item, index) {
let indexOfDefaultTrue = this.items.findIndex((item) => item.default === true);
this.items[indexOfDefaultTrue].default = false;
this.items[index].default = true;
},
All seems to be working, but the issue is that, if i search for Text 2 (for instance) and click the radio button, it turns to active, but when i clear the filter, it seems like nothing happened It only happens if i use the search method, if i click an item on the initial list, radio button changes properly. Text 2 search After i clear the search
It looks like the list didnt render the new items or something like that? Im big stucked. Thank you very much, i wish someone can help me!
<template>
<v-app>
<v-main>
<v-text-field v-model="search" label="Look for name..."></v-text-field>
<div v-for="(item, index) in filteredItems">
<div style="display: flex">
<input
type="radio"
:checked="item.default"
@click="changeDefault(item, index)"
/>
<h1>{{ item.name }}</h1>
</div>
</div>
</v-main>
</v-app>
</template>
<script>
export default {
name: 'App',
components: {},
data: () => ({
search: '',
items: [
{
default: true,
name: 'Text 1',
},
{
default: false,
name: 'Text 2',
},
{
default: false,
name: 'Text 3',
},
{
default: false,
name: 'Text 4',
},
],
}),
methods: {
changeDefault(item, index) {
console.log(item);
let indexOfDefaultTrue = this.items.findIndex((item) => item.default === true);
console.log(indexOfDefaultTrue);
this.items[indexOfDefaultTrue].default = false;
this.items[index].default = true;
console.log(this.items);
},
},
computed: {
filteredItems() {
if (this.search) {
return this.items.filter((item) => {
return item.name.toLowerCase().match(this.search);
});
} else {
return this.items;
}
},
},
};
</script>
CodePudding user response:
Full Answer:
The problem with the code is that you are using the item index within function 'changeDefault', you should instead use the name of the item, because the index is dynamic, so if you search for 'Text 2', the index that would be used is 0, and not 1:
function changeDefault(clickedItem) {
let indexOfDefaultTrue = items.findIndex((item) => item.default === true);
let indexOfbuttonClicked = items.findIndex((item) => item.name === clickedItem.name);
items[indexOfDefaultTrue].default = false;
items[indexOfbuttonClicked].default = true;
}
And the input radio:
<input
type="radio"
:checked="item.default"
@click="changeDefault(item)"
/>
CodePudding user response:
It sounds like 'filteredItems' is not reactive, is it a computed function? As it sounds like it's not rerunning every time 'this.search' is changing.
If you have a larger example of the code, I can take a look.