I would like to bind an input field to a route param in vue.js.
<input v-model="$route.params.query"/>
Is it possible?
The most straight-forward way I found was the following:
<input v-model="foo" />
--
data() {
return {
foo: this.$route.query.foo
};
},
watch: {
foo(newVal) {
this.$router.push({ query: { ...this.$route.query, foo: newVal } });
},
'$route.query.foo': function(val) {
this.foo = val;
}
}
Edit 2019-08-16: added watch for $route
to react to back navigation.
Yes, it is possible. In my code, I have a <select>
element on change of which I want to append the selected value to url as query. So, I have done like this:
My previous URL was:
localhost:8080/books
<select class="form-control" v-on:change="appendQueryToUrl" v-model="filterData.genre">
methods: {
appendQueryToUrl() {
this.$router.push({query: {genre: this.filterData.genre}})
}
}
Where genre is my key and this.filterData.genre is my local object value. Now my url looks like:
localhost:8080/books/?genre=Computer
Thanks and inform me if any error.
A bit of time has passed, but since the docs say "it is often a better idea to use a computed property rather than an imperative watch callback" I thought I would add this pattern which I tested successfully and also looks more elegant IMHO.
The idea is to use a computed
property linked to the query param with explicit get
and set
methods and bind the input with v-model
to that property.
So in your template:
<input v-model="query_param"/>
Then in your computed properties:
computed: {
query_param: {
get() {
return this.$route.query.your_query_param
},
set(value) {
/* Here I use replace so that you're not actually
pushing a new page to the history stack */
this.$router.replace({
query: { your_query_param: value }
})
}
}
}
This of course would work for a single query parameter. If you have multiple inputs you want to bind to different parameters just put additional computed properties in the same way.
©2020 All rights reserved.