Hiiiii everyone,
have a nice day,
I have a project that syncs the URL with selection on the component.
I pass the query object to the VueRouter.
The VueRouter stringify that object and use it as an URL
After that, I can get that Object through this.$route.query
object (Vuerouter will parse that URL to normal Object)
Here is the minimal version on CodeSandbox
I pass these objects to Vue router:
{ destinations: ['Hanoi'] }
{ destinations: ['Hanoi','Da Nang'] }
{ destinations: ['Ho Chi Minh City'], travelStyle:['Discovery','Adventure'] }
App.vue
<template>
<div id="app">
<div class="tour">
<h2>Which tour?</h2>
<router-link :to="{ path: 'tours', query: { destinations: ['Hanoi'] } }">Hanoi</router-link>
<br>
<router-link
:to="{ path: 'tours', query: { destinations: ['Hanoi','Da Nang'] } }"
>Hanoi - Da Nang</router-link>
<br>
<router-link
:to="{ path: 'tours', query: { destinations: ['Ho Chi Minh City'] } }"
>Ho Chi Minh City</router-link>
<br>
<br>
<span>Route Query: {{this.$route.query}}</span>
</div>
</div>
</template>
<script>
export default {
name: "App",
};
</script>
The problem is, if I using default parseQuery/StringifyQuery
of VueRouter, the URL quite of long
tours?destinations=Ho%20Chi%20Minh%20City&travelStyle=Discovery&travelStyle=Adventure
for this object: { destinations: ['Ho Chi Minh City'], travelStyle:['Discovery','Adventure'] }
I followed the instruction in this topic Custom querystring parser and add qs as a custom querystring parser.
And using an external package allow me to control the URL as what I want,
Here is inside the router file - full running project in codesandbox
// ...
const router = new VueRouter({
mode: "history",
base: "/",
routes,
stringifyQuery: (query) => {
qs.stringify(query, {
encode: false,
indices: false,
arrayFormat: "comma",
addQueryPrefix: true,
});
},
parseQuery: (query) => {
console.log("queryString", query);
const a = qs.parse(query, {
comma: true,
});
console.log("after parse:", a);
return a;
},
});
Now the URL is quite shorter when using commas in array.
tours?destinations=Hanoi
tours?destinations=Hanoi,Da%20Nang
tours?destinations=Ho%20Chi%20Minh%20City&travelStyle=Discovery,Adventure
But another problem coming up: Stringify with comma
format should add square brackets to parameter name to identity array with single value
Because using a comma to separate each element inside the array, so we cannot know that destinations=Hanoi
means { "destinations": [ "Hanoi" ] }
or { "destinations": "Hanoi" }
**When I click to routerlink to the URL tours?destinations=Hanoi
I got { "destinations": [ "Hanoi" ] }
(correct)
but if I reload that very URL I got { "destinations": "Hanoi" }
(wrong)**
From that issues, they said we can add brackets on the end of the key on an array with a single value to get what we want.
des[]=hanoi > { des: [ 'hanoi' ] }
des=hanoi,hai phong > { des: [ 'hanoi', 'hai phong' ] }
here is my test file on repl.it
const qs = require('qs');
const stringifyQuery = (query) => {
Object.keys(query).forEach((item) => {
if(Array.isArray(query[item])&&query[item].length===1) {
query[item+'[]'] = query[item];
delete query[item];
}
});
return qs.stringify(query, {
encode: false,
indices: false,
arrayFormat: 'comma',
});
};
let parseQuery = (query) =>
qs.parse(query, {
comma: true,
});
const a = {des: ['hanoi']};
const b = {des: ['hanoi','hai phong']};
console.log(stringifyQuery(a)); // des[]=hanoi
console.log(stringifyQuery(b)); // des=hanoi,hai phong
console.log(parseQuery(stringifyQuery(a))); // { des: [ 'hanoi' ] }
console.log(parseQuery(stringifyQuery(b))); // { des: [ 'hanoi', 'hai phong' ] }
It's working fine!
But when I use it on vue-router, it not.
Once again, it's showing different results between click to the router-link and reload the same URL!
For this URL tours?destinations[]=Hanoi
If I click through router-link, it still got { "destinations[]": [ "Hanoi" ] }
instead "destinations": [ "Hanoi" ]
But if I reload the page, I got the correct one: { "destinations": [ "Hanoi" ] }
I tried to figure out what happened, but it's quite touching for me as a newbie,
Does anyone have any idea or keyword in this problem?
Thanks a lot when you take your valuable time and read my long question,
It means a lot to me, I really appreciate it!