I have a search bar that is in my navbar component and with Axios, I get the articles filtered.
export default {
data() {
return {
articles: [],
article: {},
search: '',
}
},
methods: {
getArticles() {
const url = `${baseApiUrl}/search?search=${this.search}`;
axios(url).then((res) => {
this.articles = res.data;
});
}
},
watch: {
search() {
const route = {
name: 'searchArticles'
}
if(this.search !== '') {
route.query = {
search: this.search
}
}
},
'$route.query.search': {
immediate: true,
handler(value) {
this.search = value
}
}
},
};
</script>
<template>
<header class="navbar">
<form class="searchInput">
<input v-model="search" @keyup.enter="getArticles()" placeholder="Search..." />
<router-link :to="{ path: '/search', query: { search: this.search }}">
<button type="submit">
<font-icon class="icon" :icon="['fas', 'search']"></font-icon>
</button>
</router-link>
</form>
</header>
</template>
And I have my searchResult component to render the search result.
export default {
data() {
return {
articles: [],
article: {},
search: ''
}
},
created() {
const url = `${baseApiUrl}/search?search=${this.search}`;
axios(url).then((res) => {
this.articles = res.data;
});
},
watch: {
search() {
const route = {
name: 'searchArticles'
}
if(this.search !== '') {
route.query = {
search: this.search
}
}
},
'$route.query.search': {
immediate: true,
handler(value) {
this.search = value
}
}
},
};
</script>
<template>
<div>
<div class="result-search">
<ul>
<li v-for="(article, i) in articles" :key="i">
<ArticleItem :article="article" />
</li>
</ul>
</div>
</div>
</template>
When I search for the first time it takes me to /search?... and shows the search result, but if I enter another value in the field just my URL changes from /search?search=a to /search?search=b and the result remains that of search A and only when I reload the page does it bring me the result of search B. Why does it happen? all my content is centered within my content component through the
my app component:
<template>
<div id="app">
<Header :hideUserDropdown="!user" />
<Loading v-if="validatingToken" />
<Content v-else />
<Footer />
</div>
</template>
CodePudding user response:
The axios call for searching your data currently exists in your created
hook. This means it will only run on initial load of that page/component.
Move your search functionality into a method and invoke it from your watcher, ie
watch: {
'$route.query.search': {
immediate: true,
fetchArticles(value)
}
},
methods: {
async fetchArticles(val) {
let url = `${baseApiUrl}/search?search=${val}`
try {
let res = await axios(url)
this.articles = res.data
} catch (error) {
console.log(`An error occurred attempting to fetch articles with search term of ${val}: `, error)
} finally {
// do something here if you need
}
}
}
The Vue docs are great if ever you get stuck. Here's a link to Vue's lifecycle hooks and when you can use them :)