はじめに
今回作成したいのは、いわゆる「ソート機能」です。
Vue.jsのフィルターを使ってもcheckedを維持する – カバの樹
vue.jsを使って非同期に処理をします。
データはDBから取得したデータ(今回はLaravelをつかって)を利用します。
(jQueryを使ってモデルに紐付いていないデータをソートする方法は、色々あったのですがvueとLaravelを組み合わせて、データベースのデータを追加で取得する方法が無かったので今回記事を書きました。)
実装
const API_GET_DATA = '/api/data/get/'; // ①
new Vue({
data(){
return {
order: '',
orderItems: [ // ②
{name: 'おすすめ順', value: 'recommend'},
{name: '費用安い順', value: 'lowinitial'},
{name: '近い順', value: 'nearly'},
]
}
},
watch: {
/**
* 一覧の初期値取得
* 初期表示はオススメ順でソート
*/
order() {
axios.post(API_GET_DATA, {
order: this.order // ③
})
.then(res => {
this.$store.commit('setValue', res.data);
});
}
}
}
①実際に取得するデータのコントローラーまでのルーティングを記載しておきます。
②vue側のdataで予め、orderに渡す情報を記載しておきます。下のsort.htmlで利用します。
③そして、laravel側のDataGetController.phpに対して、selectで選択した値を渡す為に、apiに対してリクエストを投げます。
今回、帰ってきた値はvueのstoreに保存するようにしています。
<div class="facility__sort">
<p class="facility__sortHeader">並び替え:</p>
<div class="selectbox">
<select v-model="order" class="selectbox__input">
<option v-for="(item, index) in orderItems" :value="item.value">{{ item.name }}</option>
</select><i class="selectbox__icon"></i>
</div>
</div>
v-forで先程dataに記載したorderItemsを利用して、valueとラベルを表示させます。
それ以外はなんの変哲もないselectフォームになります。
/**
* @param Request $request
*
* @return ApiResponse
*/
public function main(Request $request)
{
$order_type = $request->input('order', 'recommend');
$data = $this->main_service->getByOrder($order_type);
return new ApiResponse(['data' => $data]);
}
DataGetController.phpでは、モデルを取得するメソッドを呼び出します
(各自設計が異なりそうなので、今回は詳細は省略します。)
リクエストで取得した$order_typeの中には、orderItemsで選択されたvalueが値に入っています。
(例: 'おすすめ順' -> value: 'recommend')
流れとしては、それぞれのモデル等で、以下のようなデータの紐づけを定義しておきます。
取得したorderItemsの値に応じて、ソートする際にどのようなカラムが必要になるのかを考え、
それぞれのカラムを定義します。
こちらをサービス等で取得し、あとはorderByなどに渡してあげれば、クエリが発行できるので、それで取得できた値をvue側にreturnすると完了です。
const ORDER_CONDITIONS = [
'recommend' => [ // おすすめ順
'order' => null
],
'lowinitial' => [ // 費用安い順
'order' => [
'initial_price_min' => 'ASC',
],
],
'nearly' => [ // 近い順
'order' => [
'distance' => 'ASC',
],
],
];
/**
* 引数で受け取ったorder_typeに応じてそれぞれのソートを呼び出す。
*
* @param $city_id
* @param $per_page
* @param $page
* @param $order_type
* @return mixed
*/
public function getByOrder($order_type)
{
if (! isset(DataModel::ORDER_CONDITIONS[$order_type])) {
$order_type = 'recommend';
}
$order_conditions = DataModel::ORDER_CONDITIONS[$order_type];
return $this->data->getByOrderType($order_condition);
}
例えば、以下のようにDataModelに定義した、並び替え情報をもとに$order_condition
(近い順だとこんな感じのデータ)
'order' => [
'distance' => 'ASC',
],
を取得できますので、これをorderBy($order_condition)としてあげると、distanceカラムでソートされます。
こんな感じで値が取得できますので、そちらをリターンしてあげると、vue側でstoreに保存というような一連の流れを作ることができました。
おわりに
いかがだったでしょうか。
意外と簡単に非同期で、ソート機能を実現できました。(私はめちゃめちゃ時間がかかりましたが
)
vueとwebアプリケーションフレームワークの融合はかゆいところに手が届く感じがして、大変重宝しております。
また、機能単位でvueとフレームワークの実装をご紹介できたらと思います。
