Query Strings and VueJS

Posted: 2018-05-08 16:44:07

Quick way to make the url reflect the query string so the user can share the url and filters.

This is component based VueJS building so not an SPA But I still install "vue-router": "^3.0.1"

And load it

import VueRouter from 'vue-router';

Vue.use(VueRouter);

The on the component I set a watch on the router.

  watch: {
    $route(to, from) {
      this.setModelFromQueryString();
      this.search();
    }
  },

In this case it will set the query strings then trigger the "search" to load the data into the page. This search becomes the go to to get state when the page is loaded (as seen below) or when the users clicks "search"

Created kicks this off the state:

  created: function() {
    this.setModelFromQueryString();
    this.search();
  },

Here is setModelFromQueryString:

    setModelFromQueryString() {
      this.params.forEach(param => {
        this[param.model] = this.getParam(param.display_name);
      });
    },

Make sure the model matches the state the user wants. The states or filters that I am trying to set are stored in data.

The data model stores theys keys and related model values that I want to focus on keeping and restoring:

  data() {
    return {
      params: [
        {
          model: 'stack_name',
          display_name: 'stack_name'
        },
        {
          model: 'project_name',
          display_name: 'project_name'
        },
        {
          model: 'current_page',
          display_name: 'page'
        },
        {
          model: 'language',
          display_name: 'language'
        },
        {
          model: 'search_name',
          display_name: 'name'
        }
      ],

Now that the model is there I can iterate over these in a few other areas I will show below.

Page load, and search call the method search and this takes care of a few things

  • make sure the the query string reflects the latest model, e.g. what the user set on the page form
  • updates the api url to have these params this.getParams('/api/libraries')

Here is search plus those methods:

search() {
      this.setQueryString();
      this.loading = true;
      axios
        .get(this.getParams('/api/libraries'))
        .then(results => {
          this.libraries = results.data;
          this.loading = false;
        })
        .catch(error => {
          console.log(error);
          $alerts.send('Error', 'Could not get next page', true);
        });
    },
    getParams(prefix) {
      let url_string = prefix + '?';
      let query = [];
      this.params.forEach(param => {
        if (this[param.model]) {
          let value = this[param.model];
          let name = param.display_name;
          query.push(`${name}=${value}`);
        }
      });
      query = query.join('&');
      return `${url_string}${query}`;
    },
    getParam(param) {
      return this.$router.history.current.query[param];
    },
    paginateFunction(page) {
      this.current_page = page;
      this.search();
    },
    setQueryString() { //This method builds up the url so the user will see the filter on page load based on their search
      let items = {};

      this.params.forEach(param => {
        if (this[param.model] != undefined) {
          items[param.display_name] = this[param.model];
        }
      });

      this.$router.push({
        query: items
      });
    },