I have a search bar on the root component (App.vue). I want to enter a query and on @keyup.enter
, it should redirect to the Search
component view with the v-text-field
input value. Redirection is used by using $router.replace
because users might search for a different keyword from within the same route.
The code below work but only ONCE. If I enter a new search term, the URL changed but the results stay the same.
App.vue
<template>
<div>
<header>
<v-text-field @keyup.enter="goToSearchPage($event)"></v-text-field>
</header>
<v-main>
<router-view></router-view>
</v-main>
</div>
</template>
<script>
export default {
methods: {
goToSearchPage($event) {
this.$router.replace({
name: "Search",
query: { q: $event.target.value }
});
}
}
};
</script>
views/Search.vue
<template>
<div>
<ais-instant-search
index-name="dev_brunjar_products"
:search-client="searchClient"
:search-function="searchFunction"
>
<ais-hits>
<ul slot-scope="{ items }">
<li v-for="item in items" :key="item.objectID">
{{ item.name }}
</li>
</ul>
</ais-hits>
</ais-instant-search>
</div>
</template>
<script>
import algoliasearch from "algoliasearch/lite";
export default {
data() {
return {
searchClient: algoliasearch(
process.env.VUE_APP_ALGOLIA_APP_ID,
process.env.VUE_APP_ALGOLIA_SEARCH_KEY
)
};
},
methods: {
// According to Algolia's doc, this should be inside data instead of methods
// https://www.algolia.com/doc/api-reference/widgets/instantsearch/vue/#widget-param-search-function
// But doing so, I wouldn't be able to get this.$route.query.q
searchFunction(helper) {
var query = this.$route.query.q;
if (query) {
helper.setQuery(query).search();
}
}
}
};
</script>
What I've tried
Did a hack-ish way (Test 1) to solve it but didn't work (which I'm glad, because it doesn't feel right). Below was the non-working code addition to the Search component. Created computed & watch property of query
which get its data from this.$route.query.q
and algoliaHelper
data assigned with AlgoliaSearchHelper when the searchFunction
first load.
When I typed a new search term, the watcher works and the query indeed changed. Despite that, calling the helper and setting its query with the new term within the watcher did not change the results from Algolia.
Then I used Routing URLs (Test 2) to the ais-instant-search
and it still didn't solve the issue. Maybe I'm implementing it wrong? I really tried to understand Algolia's doc and it's just too hard to digest.
views/Search.vue - Test 1 (Failed)
<template>
<div>
<ais-instant-search
index-name="dev_brunjar_products"
:search-client="searchClient"
:search-function="searchFunction"
>
<ais-hits>
<ul slot-scope="{ items }">
<li v-for="item in items" :key="item.objectID">
{{ item.name }}
</li>
</ul>
</ais-hits>
</ais-instant-search>
</div>
</template>
<script>
import algoliasearch from "algoliasearch/lite";
export default {
data() {
return {
searchClient: algoliasearch(
process.env.VUE_APP_ALGOLIA_APP_ID,
process.env.VUE_APP_ALGOLIA_SEARCH_KEY
),
algoliaHelper: null
};
},
computed: {
query() {
return this.$route.query.q;
}
},
watch: {
query(newQuery) {
this.algoliaHelper.setQuery(newQuery).search();
}
},
methods: {
searchFunction(helper) {
if (!this.algoliaHelper) {
this.algoliaHelper = helper;
}
if (this.query) {
helper.setQuery(this.query).search();
}
}
}
};
</script>
views/Search.vue - Test 2 (Failed)
<template>
<div>
<ais-instant-search
index-name="dev_brunjar_products"
:search-client="searchClient"
:search-function="searchFunction"
:routing="routing"
>
<ais-hits>
<ul slot-scope="{ items }">
<li v-for="item in items" :key="item.objectID">
{{ item.name }}
</li>
</ul>
</ais-hits>
</ais-instant-search>
</div>
</template>
<script>
import { history as historyRouter } from "instantsearch.js/es/lib/routers";
import { singleIndex as singleIndexMapping } from "instantsearch.js/es/lib/stateMappings";
import algoliasearch from "algoliasearch/lite";
export default {
data() {
return {
searchClient: algoliasearch(
process.env.VUE_APP_ALGOLIA_APP_ID,
process.env.VUE_APP_ALGOLIA_SEARCH_KEY
),
routing: {
router: historyRouter(),
stateMapping: singleIndexMapping("instant_search")
}
};
},
methods: {
searchFunction(helper) {
if (this.query) {
helper.setQuery(this.query).search();
}
}
}
};
</script>
I would appreciate it if you guys know how to solve this issue.
https://codesandbox.io/s/github/algolia/doc-code-samples/tree/master/Vue%20InstantSearch/routing-vue-router?file=/src/views/Home.vue
This is an example using vue router. I guess this might be what you're looking for. Please let us know if it works for you.