(Note: This article has been updated with Breeze starter kit in place of Jetstream.)
In this tutorial we’ll create simple search capability in a Laravel 8 app using VILT (Vue.js, Inertia.js, Lavarel, Tailwind) stack.
Assuming that the composer is installed, enter the following command to create new Laravel 8 project:
composer create-project laravel/laravel app 8.*
Now go inside the newly created app folder
cd app
Enter following command to add Breeze package:
composer require laravel/breeze:1.9.2
Now install Breeze with Vue and Inertia capability by entering following command:
php artisan breeze:install vue
Assuming node.js and npm are installed, enter the following command to install required node modules:
npm install
Next, setup database and Laravel environment file as usual. Here, I’m configuring SQLite database for simplicity purposes:
touch database/database.sqlite
Edit .env file as follows:
DB_CONNECTION = sqlite
You can remove DB_HOST, DB_PORT, DB_DATABASE, DB_USERNAME, DB_PASSWORD from .env when using SQLite database.
Since, initial setup of Laravel app is complete, we can start building our app. First enter the following command to create Employee model along with the migration:
php artisan make:model Employee -m
Open newly created migration file database/migrations/(time_stamp)_create_employees_table.php and then insert the desired table fields as follows;
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateEmployeesTable extends Migration
{
public function up()
{
Schema::create('employees', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('department');
$table->string('designation');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('employees');
}
}
Enter following command to migrate the above migration:
php artisan migrate
Since our database part is done for the time being; let’s move onto model and controller. First, amend the Employee model by inserting fillable array into the model. For that, open app/Models/Employee.php and insert protected $fillable array as follows:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Employee extends Model
{
use HasFactory;
protected $fillable = [
'name', 'department', 'designation'
];
}
Having done with the Model part of our app, we move onto Controller part by creating new EmployeeController as follows:
php artisan make:controller EmployeeController
Go ahead and open a newly created file at app/Http/Controllers/EmployeeController.php and insert following code:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Employee;
use Inertia\Inertia;
class EmployeeController extends Controller
{
public function index(Request $request)
{
return Inertia::render('Employees/Index', [
'employees' => Employee::when($request->term, function($query, $term){
$query->where('name', 'LIKE', '%'.$term.'%');
})->paginate(),
]);
}
}
Now, create a new folder named ‘Employees‘ in resources/js/Pages/ (be aware of capitalization). Then create Index.vue file inside resources/js/Pages/Employees folder (again watch out capitalization).
Insert following code inside Index.vue:
<template>
<div class="bg-gray-100 shadow mx-auto lg:max-w-4xl">
<div class="p-5">
<label for="search">Search name:</label>
<input id="search" type='text' v-model="term" @keyup="search" class="px-2 ml-2 text-sm rounded-lg border">
</div>
<table class="w-full">
<tr class="bg-gray-900 text-white">
<th class="px-2 py-1 text-sm font-bold text-left">ID</th>
<th class="px-2 py-1 text-sm font-bold text-left">Name</th>
<th class="px-2 py-1 text-sm font-bold text-left">Department</th>
<th class="px-2 py-1 text-sm font-bold text-left">Designation</th>
</tr>
<tr v-for="(employee, index) in employees.data" :key="index" :class="{'bg-gray-300': index%2===0}">
<td class="px-2 py-1 text-sm text-left">{{employee.id}}</td>
<td class="px-2 py-1 text-sm text-left">{{employee.name}}</td>
<td class="px-2 py-1 text-sm text-left">{{employee.department}}</td>
<td class="px-2 py-1 text-sm text-left">{{employee.designation}}</td>
</tr>
</table>
<Pagination :links="employees.links" />
</div>
</template>
<script>
import _ from 'lodash'
import Pagination from '@/Components/Pagination'
export default {
components: {
Pagination,
},
props: {
employees : Object,
},
data() {
return {
term: '',
}
},
methods:{
search: _.throttle(function(){
this.$inertia.replace(route('employees', {term:this.term}))
}, 500),
},
}
</script>
For pagination component, create Pagination.vue file inside resources/js/Components folder and insert code as follows;
<template>
<div v-if="links.length > 3">
<div class="flex flex-wrap -mb-1">
<template v-for="(link, k) in links" :key="k">
<div v-if="link.url === null" class="mr-1 mb-1 px-4 py-3 text-sm leading-4 text-gray-400 border rounded" v-html="link.label" />
<Link v-else class="mr-1 mb-1 px-4 py-3 text-sm leading-4 border rounded hover:bg-indigo-400 focus:border-indigo-500 focus:text-indigo-500" :class="{ 'bg-blue-700 text-white': link.active }" :href="link.url" v-html="link.label" />
</template>
</div>
</div>
</template>
<script>
import { Link } from '@inertiajs/inertia-vue3'
export default {
components: {
Link
},
props: {
links: Array,
},
}
</script>
Open routes/web.php and put the following line at the top of it:
use App\Http\Controllers\EmployeeController;
And then insert following route into this web.php:
Route::get('employees', [EmployeeController::class, 'index'])->name('employees');
All done. now, we should insert some data into the database to test the app. This can be achieved by directly entering data into employees table, or by creating CRUD or by seeders. Here, we’ll create a seeder to insert some data. For that purpose, execute following command to create a seeder;
php artisan make:seeder EmployeeSeeder
Modify the newly created database/seeders/EmployeeSeeder.php as follows;
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class EmployeeSeeder extends Seeder
{
public function run()
{
$faker = \Faker\Factory::create();
for($i=0;$i<200;$i++){
DB::table('employees')->insert([
'name' => $faker->name,
'department' => Str::random(10),
'designation' => Str::random(10),
]);
}
}
}
Now run the following command to insert 200 employees with random names and weird random strings for other fields in the table;
php artisan db:seed --class=EmployeeSeeder
Finally, execute the following command to compile UI assets:
npm run dev
Run Laravel development server by executing:
php artisan serve
Enter the following URL in your browser to display records in basic datatable which incorporates simple searching and pagination:
localhost:8000/employees
If you want to display records in a data-table which incorporates sorting, pagination and field based searching for Laravel 8 VILT app, then follow this tutorial.