WEBOPIXEL

Laravel+Vue.jsでインクリメンタルサーチ

Posted: 2018.05.25 / Category: javascript, PHP / Tag: ,

LaravelとVue.jsを使用したインクリメンタルサーチ機能の実装例です。

Sponsored Link

Laravel 5.5
axios ^0.17
vue ^2.5.7
を使用します。

Model

Postモデルがあるとします。
フィールドもいろいろあると思いますが、今回はtitleで検索します。

app/Models/Post.php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
	protected $fillable = [
		'title', 'body'
	];
}

Router

ルーターはroutes/api.phpに設定すると、api/postsみたいにアクセスして取得できるようになります。

routes/api.php

Route::get('posts', 'Api\PostsController@index');

Controller

URLにパラメータがない場合は空の配列を返して、titleパラメータがあった場合のみ検索されるようにします。

Http/Controllers/Api/PostsController.php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Support\Facades\Input;

class PostsController extends Controller
{
    public function index()
    {
        if (!empty(Input::get('title'))) {
            $queryTitle = Input::get('title');
            return Post::select('id', 'title')
					->where('title', 'LIKE', "%$queryTitle%")
					->limit(20)->get();
        }
        return [];
    }
}

これで/api/posts?title=検索ワードのようにアクセスすることでtitleに検索ワードが含まれるレコードを返すような作りができました。

Vue.jsコンポーネント作成

新たにPostSearchComponentという名前でコンポーネントを作成します。

resources/assets/js/components/PostSearchComponent.vue

<template>
	<div>
		<input type="text" v-model="keyword">
		<div class="result-view">
			<ul>
				<li v-for="post in posts">
					{{ post.title }}
				</li>
			</ul>
		</div>
	</div>
</template>
<script>
	export default {
		data() {
			return {
				keyword: "",
				posts: {}
			}
		},
		methods: {
			search() {
				axios.get('/api/posts?title=' + this.keyword)
					.then(res => {
						this.posts = res.data;
					})
					.catch(error => {
						console.log('データの取得に失敗しました。');
					});
			}
		},
		watch: {
			keyword() {
				this.search();
			}
		}
	}
</script>

Vue.jsのイベントでkeyupというのがあり、これでキーボードで入力したときにイベントを発火できるのですが、漢字の変換でもイベントが実行されてしまいます。
なので、watchpostsを登録して、この変数が書き換えられたときイベントが発生するようにします。

次に、app.jsに作成したコンポーネントを登録します。

resources/assets/js/app.js

Vue.component('post-search', require('./components/PostSearchComponent.vue'));

最後にLaravelで表示させたいViewに登録したコンポーネントを追記しましょう。

resources/views/js/xxxx.blade.php

<post-search></post-search>