In this tutorial, we’ll be implementing server side search functionality in Vue Good table using Laravel API on the backend with VueJS on frontend.
Please note that, you must have at least some basic understandings of Laravel & VueJS to get along.
There's a new section in Vue Good Table's documentation about setting up Server side Search with remote mode, which i personally found quite helpful.
What’ll be doing?
We’ll be getting users records from the Database and pass it over to Vue-Good-table
and perform server side searching.
Project Setup
Follow along the steps for a complete guide on implementing server-side search with Laravel and Vue-Good-Table.
Create a new Laravel Project
Head over to your projects folder, in my case its ~/code
and run the following command.
laravel new vue-good-table-search-example
Setting up Database
Here we'll perform the basic operations like setting up the DB and other configurations.
Create a new database and assign values in .env
. In our case, its vuesearch
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=vuesearch
DB_USERNAME=root
DB_PASSWORD=root
Now before running our default migrations, let's create a simple Users Table Seeder.
php artisan make:seeder UsersTableSeeder
And now in UsersTableSeeder.php
/**
Run the database seeds.
*
@return void
*/
public function run() {
factory( User::class, 20 )->create();
}
Now run the migration with our seeded data.
php artisan migrate --seed
Setup API Endpoint
Also Read: Restful API in Laravel
In your routes/api.php
Route::get('users','UsersController@getRecords');
Next we'll create our controller php artisan make:controller UsersController
Now in our UsersController.php
/**
* @param Request $request
*
* @return \Illuminate\Http\JsonResponse
*/
public function getRecords( Request $request ) {
$search_query = $request->searchTerm;
$users = User::where( 'name', 'LIKE', '%' . $search_query . '%' )
->get()
->toArray();
if ( $search_query ) {
$users['searchTerm'] = $search_query ?: '';
} else {
$users['searchTerm'] = $search_query ? null : '';
}
return response()->json( [
'users' => $users
] );
}
Let’s verify response on postman or on browser
Hit the URL http://www.vue-good-table-search-example.local/api/users
and you shall see the JSON
response data.
Now that our API is done and working fine, let's head over to the frontend side.
Setup Frontend Routes
Now in our routes/web.php
Route::get('/', function () {
return view('users');
});
Now create a users blade template, in our case, we just renamed welcome.blade.php
to users.blade.php
with minor modifications.
Now inside of body
tags of users.blade.php
<div id="app">
<div class="flex-center position-ref full-height">
<div class="content">
<vue-search
endpoint={{config('app.url')}}api/users
></vue-search>
</div>
</div>
</div>
<script src="{{ asset('js/app.js') }}"></script>
We'll create our Vue Component in a while. For ease I'm used to pass API endpoint as prop to our component.
You may also define your application endpoint in config/app.php
Setup Vue Component
Rename ExampleComponent.vue
to VueSearchComponent.vue
oh wait, we forgot to run npm install
to get our frontend dependencies in place.
Run the command and add link in our users blade template.
Install Vue-good-table
If you're using Vue-good-table for the first time, head over to their documentation to learn more about it.
Now run npm install vue-good-table
and later import in our VueSearchComponent
.
Now in our VueSearchComponent.vue
<template>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">Users</div>
<div class="card-body">
<vue-good-table
mode="remote"
:columns="columns"
:rows="rows"
:globalSearch="true"
:search-options="{
enabled: true,
skipDiacritics: true,
}"
@on-search="onSearch"
styleClass="table table-hover table-bordered table-responsive">
<template slot="table-row" slot-scope="props">
<span v-if="props.column.field === 'S.No'">
{{ (users.per_page * (users.current_page - 1)) + (props.index + 1)
}}
</span>
<span v-else>
{{props.formattedRow[props.column.field]}}
</span>
</template>
</vue-good-table>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import Vue from 'vue';
import VueGoodTable from 'vue-good-table';
import 'vue-good-table/dist/vue-good-table.css'
Vue.use(VueGoodTable);
export default {
props: ['endpoint'],
data() {
return {
users: {
searchTerm: '',
total: 0,
per_page: 5,
from: 1,
to: 0,
current_page: 1
},
offset: 4,
columns: [
{
label: 'S.No',
field: 'S.No'
},
{
label: 'User Name',
field: 'name',
filterable: true
},
{
label: 'Email Address',
field: 'email',
filterable: true
},
{
label: 'Created At',
field: 'created_at',
filterable: true
},
],
rows: []
}
},
mounted() {
this.getRecords()
},
methods: {
getRecords() {
return axios.get(`${this.endpoint}?searchTerm=${this.users.searchTerm}`).then((response) => {
this.rows = response.data.users.data
this.users = response.data.users
})
},
updateParams(newProps) {
this.users = Object.assign({}, this.users, newProps);
},
onSearch: _.debounce(function (params) {
this.updateParams(params);
this.getRecords();
return false;
}, 500)
}
}
</script>
Now run npm run dev
to build our assets and head over to your browser to see the server side searching in action.
Bonus Section: How about adding Pagination now?
To setup pagination, let's make few changes to our API. Back to our UsersController.php
$search_query = $request->searchTerm;
$perPage = $request->per_page;
$users = User::where( 'name', 'LIKE', '%' . $search_query . '%' )
->paginate( $perPage )
->toArray();
We'll create a separate Paginator.vue
component for our server-side Pagination and include it into our main VueSearchComponent
.
Create a new Paginator component and add it in our app.js
Vue.component('pagination', require('./components/Paginator'));
Now in Paginator.vue
<template>
<ul class="pagination">
<li v-if="pagination.current_page > 1" class="page-item" >
<a href="javascript:void(0)" aria-label="Previous" v-on:click.prevent="changePage(pagination.current_page - 1)">
<span aria-hidden="true">«</span>
</a>
</li>
<li v-for="page in pagesNumber" :class="{'active': page == pagination.current_page}">
<a href="javascript:void(0)" v-on:click.prevent="changePage(page)">{{ page }}</a>
</li>
<li v-if="pagination.current_page < pagination.last_page">
<a href="javascript:void(0)" aria-label="Next" v-on:click.prevent="changePage(pagination.current_page + 1)">
<span aria-hidden="true">»</span>
</a>
</li>
</ul>
</template>
<script>
export default{
props: {
pagination: {
type: Object,
required: true
},
offset: {
type: Number,
default: 4
}
},
computed: {
pagesNumber() {
if (!this.pagination.to) {
return [];
}
let from = this.pagination.current_page - this.offset;
if (from < 1) {
from = 1;
}
let to = from + (this.offset * 2);
if (to >= this.pagination.last_page) {
to = this.pagination.last_page;
}
let pagesArray = [];
for (let page = from; page <= to; page++) {
pagesArray.push(page);
}
return pagesArray;
}
},
methods : {
changePage(page) {
this.pagination.current_page = page;
this.$emit('paginate');
}
}
}
</script>
<style>
.pagination > .active > a, .pagination > .active > a:focus{
border-color:#004590;
background-color:red;
}
.pagination {
list-style: none;
display: inline-flex
}
</style>
Now we'll make slight changes to our VueSearchComponent
for pagination.
<vue-pagination :pagination="users"
@paginate="getRecords()"
:offset="4">
</vue-pagination>
Now for our axios call, we'll have to pass the page
and per_page
attributes likeso,
getRecords() {
return axios.get(`${this.endpoint}?searchTerm=${this.users.searchTerm}&page=${this.users.current_page}&per_page=${this.users.per_page}`).then((response) => {
this.rows = response.data.users.data
this.users = response.data.users
})
},
Also, don't forget to import the Paginator
component to your VueSearchComponent
.
import VuePagination from './Paginator';
and
components: {
VuePagination,
},
Now for the final time, run npm run dev
and head back to your browser to see server-side pagination and search in action. Bam!
Conclusion
We've successfully implemented Server-side Search and Pagination with Vue-good-table and Laravel. If you've any queries or feedbacks, do leave us a comment below.
For complete application setup, you may check out the Github Repo for Vue Server Side Search Example.