I have 2 components in my project where I tried create query based search filter
- PostsList component:
<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>
- PostFilter component:
<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>
Advertisement
Answer
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};