saj sta
saj sta

Reputation: 95

vue js append params to URL

I am new to vuejs and I am making an app which should filters all the data from database and filter parameters should be passed in URL, so that it remain in the page even after page refresh. Firstly, I want to push search params in URL My current Url localhost:8080/product I want my Url to be like below when user click checkboxes localhost:8080/product?color=red&color=green&size=small (When user checks red, green and small options)

So far, I have done this and I am stuck how to get dynamic color in $this.router.push(), and append it to URL

<template>
    <div class="products">
        <h1>Filter By Color</h1>
        <input @click="filterData" v-model="colortype" type="checkbox">Red color
        <input @click="filterData" v-model="colortype" type="checkbox">Green color
        <input @click="filterData" v-model="colortype" type="checkbox">Yellow color
        <h1>Filter By Size</h1>
        <input @click="filterData" v-model="size" type="radio">Big
        <input @click="filterData" v-model="size" type="radio">Small
    </div>
</template>

    <script>
        export default {
            data() {
                return {
                    colortype:''
                }
            },
            methods:{
                filterData() {
                    this.$router.push({ path: "product", query: { color: "red" } });
                }
            }
        }
    </script>

Any suggestions, once I push params to URL, I want to do api request to endpoint in filterData method.

Upvotes: 1

Views: 2393

Answers (1)

user19015424
user19015424

Reputation: 211

There is a pattern you can use for this:

  1. Store the filter values on an object
  2. Deeply watch the filter object and react to it by fetching data / updating url.

The following snippets demonstrate a dropdown where you can pick one value to filter on.

<template>
<div>
  Color:
  <select v-model="filter.color">
    <option v-for="item in colors" :key="item.value" :value="item.value">
      {{ item.name }}
    </option>
  </select>
</div>
</template>
export default {
  name: "MyComponent",
  data: () => ({
    filter: {
      color: null,
    },
    colors: [{name: 'Black', value: 'black'}, {name: 'Red', value: 'red'}],
  }),
  watch: {
    'filter': {
      deep: true,
      handler(filter) {
        this.$router.replace({
           ...this.$route,
           query: {
             color: filter.color.value,
             // TODO: Convert `filter` to params
           },
        });
        this.search(filter);
      },
    },
  },
};

For the case where there a field accepts multiple values (e.g. using checkboxes) I'd suggest to put all values on the filter object and have each option mark its checked-ness with a flag. The following snippets demonstrate that technique:

<template>
  <div>
    Sizes:
    <label v-for="size in sizes" :key="size.value">
      <input type="checkbox" v-model="size.active">
      {{ size.name }}
    </label>
  </div>
</template>
export default {
  data: () => ({
    filter: {
      sizes: [{name: 'Small', value: 'small', active: false}],
    },
  }),
  watch: {
    filter: {
      deep: true,
      handler() {
        this.$router.replace({
          ...this.$route,
          params: {
            sizes: this.filter.sizes
              .filter(size => size.active)
              .map(size => size.value)
              .join('+'),
          },
        });
      },
    },
  },
}

Upvotes: 1

Related Questions