Reputation: 5024
I have 2 components in my project where I tried create query based search filter
<template>
<div>
<PostFilter @change-filter="setFilters" />
<h3>Active filters</h3>
<pre>{{ activeFilters }}</pre>
<h3>Updated filters</h3>
<pre>{{ updatedFilters }}</pre>
</div>
</template>
<script>
import PostFilter from "../../components/posts/PostFilter.vue";
export default {
components: {
PostFilter,
},
data() {
return {
updatedFilters: {},
activeFilters: {
category: "",
query: "",
perPage: 5,
page: 1,
},
};
},
methods: {
setFilters(updatedFilters) {
console.log("Active filters");
console.log(this.activeFilters);
console.log("Updated filters");
console.log(updatedFilters);
this.$router.push({ query: updatedFilters });
if (this.$route.query.page) {
updatedFilters.page = 1;
}
this.activeFilters = updatedFilters;
},
objectEquals(obj1, obj2) {
for (var i in obj1) {
// eslint-disable-next-line
if (obj1.hasOwnProperty(i)) {
// eslint-disable-next-line
if (!obj2.hasOwnProperty(i)) return false;
if (obj1[i] !== obj2[i]) return false;
}
}
for (var j in obj2) {
// eslint-disable-next-line
if (obj2.hasOwnProperty(j)) {
// eslint-disable-next-line
if (!obj1.hasOwnProperty(j)) return false;
if (obj1[j] !== obj2[j]) return false;
}
}
return true;
},
},
};
</script>
<template>
<div>
<select class="category" v-model="filters.category" name="category">
<option value="" selected>All categories</option>
<option
v-for="(category, index) in categories"
:key="index"
:value="category.id"
>
{{ category.title }}
</option>
</select>
<input
class="search"
v-model="filters.query"
type="search"
name="query"
placeholder="Search..."
/>
<select class="perPage" v-model="filters.perPage" name="perPage">
<option value="5">5 items / page</option>
<option value="10">10 items / page</option>
<option value="15">15 items / page</option>
<option value="20">20 items / page</option>
</select>
</div>
</template>
<script>
export default {
emits: ["change-filter"],
created() {
const query = this.$route.query;
if (
query &&
Object.keys(query).length > 0 &&
query.constructor === Object &&
this.hasFilterKeys(query)
) {
this.filters = { ...this.filters, ...this.$route.query };
}
this.fecthCategories();
},
data() {
return {
filters: {
category: "",
query: "",
perPage: 5,
},
awaitingSearch: false,
categories: [],
};
},
watch: {
"filters.category": function (currentValue, oldValue) {
if (oldValue !== currentValue) {
this.emitFilters();
}
},
"filters.query": function (currentValue, oldValue) {
// eslint-disable-next-line
if (oldValue != currentValue) {
if (!this.awaitingSearch) {
setTimeout(() => {
this.emitFilters();
this.awaitingSearch = false;
}, 1000);
}
this.awaitingSearch = true;
}
},
"filters.perPage": function (currentValue, oldValue) {
if (oldValue !== currentValue) {
this.emitFilters();
}
},
},
methods: {
emitFilters() {
let cleanFilters = this.cleanObject(this.filters);
this.$emit("change-filter", cleanFilters);
},
cleanObject(obj) {
for (var propName in obj) {
if (
obj[propName] === null ||
obj[propName] === undefined ||
obj[propName] === ""
) {
delete obj[propName];
}
}
return obj;
},
async fecthCategories() {
this.categories = [
{
id: 1,
title: "Anatomy",
},
{
id: 2,
title: "Bialogy",
},
{
id: 3,
title: "Algebra",
},
{
id: 4,
title: "Chemistry",
},
{
id: 5,
title: "Computer science",
},
{
id: 6,
title: "English",
},
];
},
hasFilterKeys(obj) {
for (const key in this.filters) {
// eslint-disable-next-line
if (obj.hasOwnProperty(key) && obj[key] != "") {
return true;
}
}
return false;
},
},
};
</script>
I must send one API request when filters is change/update. But why I get same values in activeFilters
and in coming filters from method setFilters()
of PostsList component on everytime?
Why I lose old value of activeFilters
before set new values in my case?
You can see here real working example
Also here example video
<blockquote class="imgur-embed-pub" lang="en" data-id="a/Y4gauRM" ><a href="//imgur.com/a/Y4gauRM">Same object values on search</a></blockquote><script async src="//s.imgur.com/min/embed.js" charset="utf-8"></script>
Upvotes: 0
Views: 155
Reputation: 43166
The object references in chrome developer console is "alive".
Consider this example:
let x = {a: 'b'}
console.log("Active filters", x);
x.a = 'c';
this will output:
Active filters {a: "c"}
instead of Active filters {a: "b"}
You can use the spread operator to create a new object as value of activeFilters
in your example to see different values:
this.activeFilters = {...updatedFilters};
Upvotes: 1