Vue-router: Update path query string on changes to $route.query

Created on 13 Apr 2016  路  9Comments  路  Source: vuejs/vue-router

I have a pagination widget like http://materializecss.com/pagination.html in a website and when the user clicks on it to change the page, I just change an attribute from $route.query (page) and reload an ajax with the data. The problem is that the user is left without a proper anchor for the current page with the current data, as $route.query is not updated in the path.

It would be nice if those two were kept on sync.

Most helpful comment

A note to @imaia's comment: In Vue2, the same now holds for vue.router and this.$router.replace({query: {foo: "bar"}}).

All 9 comments

+1, would love to change the query param in a Vuex action and get it synced with the url query. One possible solution for now is to use router.go method every time I want to change the query param and handle the data router hook to cause a Vuex action to run.

{
  vuex: {
    actions: {
      pageChanged,
      queryItems
    }
  },
  methods: {
    onQueryChanged (query) {
      this.pageChanged(1);
      this.updateRoute(query);
    },
    onPageChanged (page) {
      this.pageChanged(page);
      this.updateRoute(Object.assign(this.$route.query, {page}));
    },
    updateRoute (query) {
      this.$route.router.go({
        name: 'search',
        query
      });
    }
  },
  route: {
    data () {
      // handle updated route
      this.queryItems(this.$route.query);
    }
  }
}

+1 for this feature

You should be using $router.go to change the query, because you are changing the URL. The query object is just a result of URL change, the URL is the source of truth. It doesn't make sense to mutate the query directly, similar to how you shouldn't try to mutate a computed property.

@caliber01 If router.go is called with query argument only, it does not reload the page, which is what I expected, so, in my approach here, I'm calling .go with query then sending a signal to my parent components to update their data.

@imaia Well, I only tried calling router.go with current route name, so that the redirect actually happens and the vue router data hook is called again.

@yyx990803 Vue offers seamless data binding for all kinds of inputs and it is one of its strongest features. Why treat the url bar differently? Why not make it easier to keep the url and the model in sync, like we do for all other inputs?

I think query-change reload the subview that make sense.

A note to @imaia's comment: In Vue2, the same now holds for vue.router and this.$router.replace({query: {foo: "bar"}}).

If none of these methods worked for you which probably won't because the route object is immutable and hence readonly, changing them won't change the current route object. If you're replacing/pushing the new data within a predefined method like following

methods: {
        search: function () {
   this.$router.push({path:'/search', query:{q: new_query}})
}
...

You should define a watcher for route and use this.$router.go() inside that watcher.

    watch: {
        '$route' (to, from) {
         if(from.query.q && to.query.q){ 
            this.$router.go()
           }    
       }
    },

Why it behaves so, I don't know. Probably it's a namespace conflict or it's just how router.go() works (depends on the namespace of the attributes in which it's been called, etc.) either way it's an unclear abstraction problem.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

gil0mendes picture gil0mendes  路  3Comments

Atinux picture Atinux  路  3Comments

saman picture saman  路  3Comments

achen224 picture achen224  路  3Comments

lbineau picture lbineau  路  3Comments