フロントエンドをvueで実装しているアプリがあります。
formでいろんなパラメータを渡したり、DOMリストに対してフィルターをかけたりと
複数のパラメータをサーバー側に渡したいケースがあります。
そういう時、$dataでパラメータをまとめてobjectとして持たせる事が多いのですが、
そのまま渡してしまうと未入力のフィルターも渡してしまい、非効率です。
選択されている項目だけ渡したかったので、objectに対してfilterメソッドを使い
未入力のフィルターを除外してGETリクエストのURLにくっつける、という処理を書きました。
フィルターには、チェックボックスとラジオボタンを使用してますが、他のinput属性でもできます。
結論
チェックボックスやラジオボタンが選択されていた場合、
選択したパラメータをURLに付与します。
*URLは localhost:3000/app/filter
で固定にしています。
*ハッシュがついてたりする場合はよしなにパースしてください。今回は#hash_sample
をつけています
コード解説
肝になる部分だけ
() => {
let pathName = 'localhost:3000/app/filter';
const hash = '#hash_sample';
const query = Object.entries(vm.$data.selectedFilter).filter(v => {
return (Array.isArray(v) && v.length > 0) || (!Array.isArray(v) && v === null)
}).map(v => {
// キャメルケースの場合はスネークケースに変換する
v[0] = v[0].split(/(?=[A-Z])/).join('_').toLowerCase();
return v.join('=');
}).join('&');
if (query !== '') pathName += `?${query}`;
pathName += `${hash}`;
vm.$data.result = pathName;
}
オブジェクトをfilterしてからmapで配列にして、&で繋いでいます。
filterで、選択されていないinput属性を渡さないようにします。
今回は、チェックボックスとラジオボタンなので以下の条件でfilterしました。
- チェックボックス
- 配列 && 長さが0以上
- ラジオボタン
- 配列以外 && null以外
使用してるinputによってfilterの条件はよしなに変更します。
ラジオボタンも、0がdefault値として絞り込みなしの条件になっていたら
みたいにしてもOKです。v === null || v === 0
script部分
let vm = new Vue({
el: "#app",
data: {
checkbox: {
name: 'checkbox',
items: [
{label: 'check_1', value: 1},
{label: 'check_2', value: 2}
],
},
radio: {
name: 'radio',
items: [
{label: 'default', value: 0},
{label: 'radio_1', value: 1},
{label: 'radio_2', value: 2}
],
},
selectedFilter: {
checkbox: [],
radio: 0
},
result: 'localhost:3000/app#hash_sample',
},
methods: {
filter: () => {
let pathName = 'localhost:3000/app/filter';
const hash = '#hash_sample';
const query = Object.entries(vm.$data.selectedFilter).filter(v => {
return (Array.isArray(v) && v.length > 0) || (!Array.isArray(v) && v === null)
}).map(v => {
v[0] = v[0].split(/(?=[A-Z])/).join('_').toLowerCase();
return v.join('=');
}).join('&');
if (query !== '') pathName += `?${query}`;
pathName += `${hash}`;
vm.$data.result = pathName;
}
}
})
HTML部分
<div id="app">
<h3>絞り込みのフィルター的なもの</h3>
<p>選択されたitem: {{ selectedFilter }}</p>
<div class="container">
<div class="filter">
<template v-for="item in checkbox.items">
<label :for="item.label">
<input
v-model="selectedFilter.checkbox"
:name="checkbox.name"
type="checkbox"
:value="item.value"
:id="item.label"
/>
{{ item.label }}
</label>
</template>
</div>
<div class="filter">
<template v-for="item in radio.items">
<label :for="item.label">
<input
v-model="selectedFilter.radio"
:name="radio.name"
type="radio"
:value="item.value"
:id="item.label"
/>
{{ item.label }}
</label>
</template>
</div>
<button @click="filter()">絞り込み</button>
</div>
<div>
<span class="label">result</span>
<span class="result">{{ result }}</span>
</div>
</div>
まとめ
objectにまとめたフィルターを、選択されている分だけGETで渡す方法を紹介しました。
もっと効率的なやり方もあるかもしれません。
そもそも、未入力のフィルターを渡しても、サーバー側で除外すれば済む話でもあるので
設計によっては使えない方法かもしれません。
Vue内でフィルター項目を定義できるケースもあれば、サーバーからフィルター項目を取得するケースもあると思います。
どんなケースであっても、とりあえずobjectにまとめて渡せるようにしておきたいなと思ったので、
今回の方法を紹介しました。誰かの役に立てば嬉しいです。