I've worked through this guide to create a search filter input field but can't figure out how to correctly implement computed
in the v-model
.
I've transformed the code from the guide into:
<template>
<div id="table-cms" >
<input type="search" placeholder="Search" v-model="filter">
<p>{{ filter }}</p>
<p>{{ state.array }}</p>
</div>
</template>
<script setup>
import {computed, reactive} from "vue";
const state = reactive({
search: null,
array: [
{id: 1, title: 'Thanos', content: '123'},
{id: 2, title: 'Deadpool', content: '456'},
{id: 3, title: 'Batman', content: '789'}
]
})
const filter = computed({
get() {
console.log('check1')
return state.search
},
set() {
if (state.search) {
console.log('check2a')
return state.array.filter(item => {
return state.search
.toLowerCase()
.split(" ")
.every(v => item.title.toLowerCase().includes(v))
});
} else {
console.log('check2b')
return state.array;
}
}
})
</script>
But the console shows:
check1
check2b
check2b
check2b
...
This means that computed
gets executed but it doesn't enter if (state.search) {}
(the actual filter). Displaying state.array
does render the initial array but does not get updated by typing different titles in the input field:
<p>{{ state.array }}</p>
rendering:
[
{
"id": 1,
"title": "Thanos",
"content": "123"
},
{
"id": 2,
"title": "Deadpool",
"content": "456"
},
{
"id": 3,
"title": "Batman",
"content": "789"
}
]
What am I doing wrong?
CodePudding user response:
You have to use state.search
as the v-model
on your input:
<input type="search" placeholder="Search" v-model="state.search">
Otherwise it stays null
forever because it is not changing which causes the code to skip the if statement.
Also you don't need a setter in your computed filter.
<template>
<div id="table-cms" >
<input
type="search"
placeholder="Search"
v-model="state.search"
/>
<p>{{ state.array }}</p>
</div>
</template>
<script setup>
import { computed, reactive } from "vue";
const state = reactive({
search: null,
array: [
{ id: 1, title: "Thanos", content: "123" },
{ id: 2, title: "Deadpool", content: "456" },
{ id: 3, title: "Batman", content: "789" },
],
});
const filter = computed(() => {
if (state.search) {
//console.log('check2a')
return state.array.filter((item) => {
return state.search
.toLowerCase()
.split(" ")
.every((v) => item.title.toLowerCase().includes(v));
});
} else {
console.log("check2b");
return state.array;
}
});
</script>