Autocomplete using Laravel 9 and Vue js 3
In today's tutorial, we are going to build an autocomplete with Laravel 9 and Vue js 3, this feature makes it easy for users to find what they are looking for in your website.
Add the search method
I assume that you have already created a new Laravel application with Vue js already installed, and you have a database with a posts table and a controller PostController.
Next, we will add a search by term method that looks for the post titles that start or end with the search term.
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
//
public function searchByTerm(Request $request){
$posts = Post::orderBy('created_at','desc')
->where('title','like','%'.$request->term.'%')
->get();
return response()->json($posts);
}
}
Create the route
Next, we will add the route in the file api.php.
Route::post('search',[PostController::class,'searchByTerm']);
Create the home component
In resources/js, we add new folder components inside the created folder we add a new file Home.vue, inside this file, we have the search field and we display the data retrieved from the API.
The structure of the folders:
- resources
- js
- components
- Home.vue
- components
- js
<template>
<div class="row my-5">
<div class="col-md-6 mx-auto">
<div class="card my-4">
<div class="card-body">
<div class="form-group mb-2">
<input
class="form-control me-2"
type="text"
v-model="data.term"
@keyup="getPostsByTerm"
placeholder="Search" aria-label="Search">
</div>
<div class="list-group" v-for="post in data.posts" :key="post.id">
<li class="list-group-item list-group-item-action">
<div class="d-flex w-100 justify-content-between">
<h6>
{{post.title}}
</h6>
</div>
<div class="mb-1">
<div>
<p>
{{post.body}}
</p>
</div>
</div>
</li>
</div>
<ul class="list-group" v-if="data.message">
<li class="list-group-item">
{{data.message}}
</li>
</ul>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { reactive } from 'vue';
const data = reactive({
posts: [],
term: ''
});
const getPostsByTerm = async () => {
clearResults();
if(data.term.length > 3){
try{
const response = await axios.post('/api/search',{
term: data.term
});
if(response.data.length){
data.posts = response.data;
}else{
data.message = 'Nothing found!';
}
}catch(error){
console.log(error);
}
}
};
const clearResults = () => {
data.posts = [];
data.message = '';
}
</script>
<style>
</style>