9

I would like to bind an input field to a route param in vue.js.

<input v-model="$route.params.query"/>

Is it possible?

3 Answers 3

22

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.

Sign up to request clarification or add additional context in comments.

1 Comment

For me, this.$router.currentRoute.query.foo was required in the data function
14

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: {
            ...this.$route.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.

Comments

1

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.

1 Comment

Your solution is a one-way binding. If we open localhost:8080/books/?genre=Computer in a new browser window, the input won't be the value of the "genre" param.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.