【Laravel / Vue】駅検索セレクトボックス実装

LaravelとVueを使用して駅検索セレクトボックスを実装する
Vueは2...時間できればVue3にアップデートします..

テーブルを作成

今回、沿線テーブル (lines)と駅テーブル (stations)にデータがある前提で進める
データの取得方法は以下を参照

駅データを取得

  • app/Providers/AppServiceProvider.php
<?php

namespace App\Providers;

use App\Models\Station;
use Illuminate\Routing\UrlGenerator;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
  // ...(省略)


   /**
     * Bootstrap any application services.
     *
     * @param UrlGenerator $url
     * @return void
     */
    public function boot(UrlGenerator $url)
    {
        // 追加
        if (Schema::hasTable('stations')) {
            view()->share('stations', Station::orderBy('name')->get());
        }
    }
}

Controllerとかで随時取得してviewに渡してもOK

他の画面でも共通で使用しやすくするために今回はAppServiceProviderで共通変数として設定してる

検索用のVueコンポーネントを作成

  • SelectStation.vue
<template>
    <div>
        <input type="text" v-model="stationName" @focus="onFocus" @blur="onBlur" placeholder="駅名を入力してください" />
        <input type="hidden" name="station_id" v-model="selectedStationId">
        <ul class="suggest-station-list" v-if="filteredStations.length !== 0 && isDisplaySuggest">
            <li v-for="station in filteredStations" :key="station.id" @click="setStation(station)">
                {{ station.name }}駅
            </li>
        </ul>
    </div>
</template>

<script>
export default {
    name: 'SelectStation',

    props: {
        stations: {
            type: Array,
            required: true,
        },
    },

    data() {
        return {
            stationName: '',
            selectedStationId: '',
            isDisplaySuggest: false,
        };
    },

    computed: {
        /**
         * 駅名入力の値からサジェスト候補を絞り込み
         * @returns {*[]|*[]}
         */
        filteredStations() {
            return this.stationName !== '' ? this.stations.filter(station => station.name.includes(this.stationName)) : []
        }
    },

    methods: {
        /**
         * 駅名入力にフォーカス時
         */
        onFocus() {
            this.isDisplaySuggest = true
        },

        /**
         * 駅名入力から離脱時
         */
        onBlur() {
            if (this.selectedStationId === '') {
                this.stationName = '駅';
            }
            setTimeout( () => this.hideSuggest(), 100)
        },

        /**
         * 候補リストを非表示
         */
        hideSuggest() {
            this.isDisplaySuggest = false
            if (this.selectedStationId === '') {
                // 何も選択されていない場合は駅名も強制リセット
                this.stationName = '';
            }
        },

        /**
         * 候補リストから選択時、駅情報を設定
         * @param station
         */
        setStation(station) {
            this.selectedStationId = station.id;
            this.stationName = station.name + '駅';
            this.isDisplaySuggest = false
        }
    }
};
</script>

  • app.jsに上記コンポーネントを追加

Viewから呼び出し

  • AppServiceProviderで共通変数にした$stationsを上記Vueコンポーネントに渡す
<select-station :stations='@json($stations)'></select-station>

こんな感じになる

\ 案件のご依頼・ご相談はこちらから /