Laravel 10 Ajax jQuery Crud with Pagination and Live Search
Laravel is a popular PHP web framework that provides developers with a wide range of features for building web applications. One of the most common tasks when building a web application is the implementation of CRUD (Create, Read, Update, Delete) operations. In this article, we will look at how to implement a Laravel CRUD application with pagination that uses jQuery and Ajax. For build a laravel ajax crud applicaion we need to follow the bellow steps.
Step 1. Setting up the Laravel Application
To get started, we need to create a new Laravel project using the command-line interface. Open up your terminal and type the following command:
composer create-project --prefer-dist laravel/laravel laravel-ajax-jquery-crud
This will create a new Laravel project in a folder called laravel-ajax-jquery-crud
. Once the project has been created, we need to create a new database and configure our .env
file with our database credentials.
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel-ajax-jquery-crud
DB_USERNAME=root
DB_PASSWORD=
Step 2. Creating the Database Table and Model
Next, we need to create a new migration for the products
table. Run the following command in the terminal:
php artisan make:migration create_products_table --create=products
This command will generate a new migration file for us. Open the migration file located in database/migrations
and add the necessary columns for the products
table.
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->double('price');
$table->timestamps();
});
}
Once you have defined your migration, run the migration to create the products
table in your database:
php artisan migrate
Step 3. Creating the Product Model
Now that we have our database table set up, we need to create a model for our products
table. Run the following command to generate a new model for the products
table:
php artisan make:model Product
This command will create a new Product
model in the app/Models
directory.
Step 4. Defining the Product Controller
With our database table and model created, we can now create a controller. Run the following command to generate a new controller for the products:
php artisan make:controller ProductController
This command will create a new ProductController
in the app/Http/Controllers
directory. Open the ProductController
and add the necessary methods for handling the CRUD operations.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Product;
class ProductController extends Controller
{
public function products()
{
$products = Product::latest()->paginate(5);
return view('products',compact('products'));
}
//paginate product
function paginateData(Request $request)
{
if($request->ajax())
{
$products = Product::latest()->paginate(5);
return view('pagination_products', compact('products'))->render();
}
}
//store product
public function addProduct(Request $request)
{
$request->validate(
[
'name'=>'required',
'price'=>'required',
],
[
'name.required'=>'Product Name is Required',
'price.required'=>'Product Price is Required',
]
);
$product = new Product();
$product->name = $request->name;
$product->price = $request->price;
$product->save();
return response()->json([
'status'=>'success',
]);
}
//update product
public function updateProduct(Request $request)
{
$request->validate(
[
'up_name'=>'required',
'up_price'=>'required',
],
[
'up_name.required'=>'Product Name is Required',
'up_price.required'=>'Product Price is Required',
]
);
Product::where('id',$request->up_id)
->update(['name'=>$request->up_name,'price'=>$request->up_price]);
return response()->json([
'status'=>'success',
]);
}
//delete product
public function deleteProduct(Request $request)
{
Product::find($request->product_id)->delete();
return response()->json([
'status'=>'success',
]);
}
//search product
public function searchProduct(Request $request)
{
$products = Product::where('name', 'like', '%'.$request->search_string.'%')
->orWhere('price', 'like', '%'.$request->search_string.'%')
->orderBy('id', 'desc')
->paginate(5);
if($products->count() >= 1){
return view('pagination_products', compact('products'))->render();
}else{
return response()->json([
'status'=>'nothing found'
]);
}
}
}
Step 5. Defining the blade files
Now we will create all the required blade files at resources/views directory.
products.blade.php
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxst.icons8.com/vue-static/landings/line-awesome/line-awesome/1.3.0/css/line-awesome.min.css">
<link rel="stylesheet" href="http://cdn.bootcss.com/toastr.js/latest/css/toastr.min.css">
<title>Ajax Crud</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8">
<h4 class="text-center mt-5">Laravel <strong>9</strong> Ajax Crud</h4>
<a href="" class="btn btn-info my-3 text-right" data-bs-toggle="modal" data-bs-target="#addModal">Add Product</a>
<input type="text" name="search" id="search" class="form-control mb-3" placeholder="Search Here.....">
<div class="table-data">
<table class="table table-bordered">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Price</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
@foreach($products as $key=>$pro)
<tr>
<td>{{ $key+1 }}</td>
<td>{{ $pro->name }}</td>
<td>{{ $pro->price }}</td>
<td>
<a href=""
class="btn btn-success edit_product_form"
data-bs-toggle="modal"
data-bs-target="#editModal"
data-id="{{ $pro->id }}"
data-name="{{ $pro->name }}"
data-price="{{ $pro->price }}"
>
<i class="las la-edit"></i>
</a>
<a href="" data-product_id="{{ $pro->id }}" class="btn btn-danger delete_product">
<i class="las la-times"></i>
</a>
</td>
</tr>
@endforeach
</tbody>
</table>
{!! $products->links() !!}
</div>
</div>
</div>
</div>
@include('add_product_modal')
@include('edit_product_modal')
@include('product_js')
{!! Toastr::message() !!}
</body>
</html>
add_product_modal.blade.php
<!-- Modal -->
<div class="modal fade" id="addModal" tabindex="-1" aria-labelledby="addModalLabel" aria-hidden="true">
<div class="modal-dialog">
<form action="{{ url('add-product') }}" method="post" id="addProductForm">
@csrf
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addModalLabel">Add Product</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="errorMsgntainer mb-3">
</div>
<div class="form-group">
<label for="product_name">Name</label>
<input type="text" name="name" id="name" class="form-control">
</div>
<div class="form-group mt-2">
<label for="product_price">Price</label>
<input type="number" name="price" id="price" class="form-control">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary add_product">Save changes</button>
</div>
</div>
</form>
</div>
</div>
edit_product_modal.blade.php
<!-- Modal -->
<div class="modal fade" id="editModal" tabindex="-1" aria-labelledby="editModalLabel" aria-hidden="true">
<div class="modal-dialog">
<form action="{{ url('store-product') }}" method="post" id="editProductForm">
@csrf
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="editModalLabel">Edit Product</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="errorMsgntainer mb-3">
</div>
<input type="hidden" name="up_id" id="up_id">
<div class="form-group">
<label for="up_name">Name</label>
<input type="text" name="up_name" id="up_name" class="form-control">
</div>
<div class="form-group mt-2">
<label for="up_price">Price</label>
<input type="number" name="up_price" id="up_price" class="form-control">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary store_product">Save changes</button>
</div>
</div>
</form>
</div>
</div>
product_js.blade.php
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script src="http://cdn.bootcss.com/toastr.js/latest/js/toastr.min.js"></script>
<script>
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
</script>
<script>
$(document).ready(function(){
//add product
$(document).on('click','.add_product',function(e){
e.preventDefault();
let name = $('#name').val();
let price = $('#price').val();
// console.log(name+price);
$.ajax({
method:'post',
url:'{{ route('add.product') }}',
data:{
name:name,price:price,
},
success:function(res){
if(res.status=='success'){
$('#addProductForm')[0].reset();
$('#addModal').modal('hide');
$('.table').load(location.href + ' .table');
Command: toastr["success"]("Product Added Success !!", "Success")
toastr.options = {
"closeButton": true,
"debug": false,
"newestOnTop": false,
"progressBar": true,
"positionClass": "toast-top-right",
"preventDuplicates": false,
"onclick": null,
"showDuration": "300",
"hideDuration": "1000",
"timeOut": "5000",
"extendedTimeOut": "1000",
"showEasing": "swing",
"hideEasing": "linear",
"showMethod": "fadeIn",
"hideMethod": "fadeOut"
}
}
},
error:function(err){
let error = err.responseJSON;
$.each(error.errors, function (index, value) {
$('.errorMsgntainer').append('<span class="text-danger">'+value+'<span>'+'<br>');
});
}
});
})
//product show in edit form
$(document).on('click','.edit_product_form',function(){
let up_id = $(this).data('id');
let up_name = $(this).data('name');
let up_price = $(this).data('price');
$('#up_id').val(up_id);
$('#up_name').val(up_name);
$('#up_price').val(up_price);
})
//update product
$(document).on('click','.update_product',function(e){
e.preventDefault();
let up_id = $('#up_id').val();
let up_name = $('#up_name').val();
let up_price = $('#up_price').val();
// console.log(name+price);
$.ajax({
method:'post',
url:'{{ route('update.product') }}',
data:{
up_id:up_id,up_name:up_name,up_price:up_price,
},
success:function(res){
if(res.status=='success'){
$('#editProductForm')[0].reset();
$('#editModal').modal('hide');
$('.table').load(location.href + ' .table');
Command: toastr["success"]("Product Updated Success !!", "Success")
toastr.options = {
"closeButton": true,
"debug": false,
"newestOnTop": false,
"progressBar": true,
"positionClass": "toast-top-right",
"preventDuplicates": false,
"onclick": null,
"showDuration": "300",
"hideDuration": "1000",
"timeOut": "5000",
"extendedTimeOut": "1000",
"showEasing": "swing",
"hideEasing": "linear",
"showMethod": "fadeIn",
"hideMethod": "fadeOut"
}
}
},
error:function(err){
let error = err.responseJSON;
$.each(error.errors, function (index, value) {
$('.errorMsgntainer').append('<span class="text-danger">'+value+'<span>'+'<br>');
});
}
});
})
//delete product
$(document).on('click','.delete_product',function(e){
e.preventDefault();
if(confirm('Are you sure to delete')){
let product_id = $(this).data('product_id');
// console.log(product_id);
$.ajax({
url:"{{ route('delete.product') }}",
method:'post',
data:{product_id:product_id},
success:function(res){
if(res.status=='success'){
// console.log('Delete Success');
$('.table').load(location.href + ' .table');
Command: toastr["warning"]("Product Delete Success !!", "Success")
toastr.options = {
"closeButton": true,
"debug": false,
"newestOnTop": false,
"progressBar": true,
"positionClass": "toast-top-right",
"preventDuplicates": false,
"onclick": null,
"showDuration": "300",
"hideDuration": "1000",
"timeOut": "5000",
"extendedTimeOut": "1000",
"showEasing": "swing",
"hideEasing": "linear",
"showMethod": "fadeIn",
"hideMethod": "fadeOut"
}
}
}
});
}
})
//pagination
$(document).on('click', '.pagination a', function(e){
e.preventDefault();
var page = $(this).attr('href').split('page=')[1];
products(page);
});
function products(page){
$.ajax({
url:"/pagination/paginate-data?page="+page,
// url:"{{ route('paginate.product').'?page='.'page'}}",
success:function(res){
$('.table-data').html(res);
}
});
}
//search product
$(document).on('keyup',function(e){
e.preventDefault();
let search_string = $('#search').val();
$.ajax({
url:"{{ route('search.product') }}",
method:'GET',
data:{search_string:search_string},
success:function(res){
$('.table-data').html(res);
if(res.status=='nothing found'){
$('.table-data').html('<span class="text-danger">'+'Nothing Found'+'</span>');
}
}
});
})
})
</script>
pagination_products.blade.php
<table class="table table-bordered">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Price</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
@foreach($products as $key=>$pro)
<tr>
<td>{{ $key+1 }}</td>
<td>{{ $pro->name }}</td>
<td>{{ $pro->price }}</td>
<td>
<a href=""
class="btn btn-success edit_product_form"
data-bs-toggle="modal"
data-bs-target="#editModal"
data-id="{{ $pro->id }}"
data-name="{{ $pro->name }}"
data-price="{{ $pro->price }}"
>
<i class="las la-edit"></i>
</a>
<a href="" data-product_id="{{ $pro->id }}" class="btn btn-danger delete_product">
<i class="las la-times"></i>
</a>
</td>
</tr>
@endforeach
</tbody>
</table>
{!! $products->links() !!}
Step 6. Defining the routes in web.php
Now we have to define all the routes inside web.php file
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ProductController;
Route::get('/',[ProductController::class,'products']);
Route::post('/add-product',[ProductController::class,'addProduct'])->name('add.product');
Route::post('/update-product',[ProductController::class,'updateProduct'])->name('update.product');
Route::post('/delete-product',[ProductController::class,'deleteProduct'])->name('delete.product');
Route::get('pagination/paginate-data',[ProductController::class,'paginateData'])->name('paginate.product');
Route::get('/search-product',[ProductController::class,'searchProduct'])->name('search.product');
Now run the following command to start development serverand test the crud application:
php artisan serve
Thanks. Hope this wil help you a lot.
If you like what you are reading, please think about buying us a coffee as a token of appreciation.
We appreciate your support and are committed to providing you useful and informative content.
We are thankful for your ongoing support.
You May Read Bellow Articles:
Laravel 9 live search data in a table using ajax.
How to send SMS in laravel 9 using Twilio SMS API-Webjourney
Laravel 9 pdf invoice generate and download with barryvdh dompdf
How to create multi language website by laravel 9
Laravel 10 multiple form validation on the same page-WebJourney
Laravel 10 Breeze Authentication - WebJourney
Laravel 10 Ajax jQuery Crud with Pagination and Live Search
Laravel Naming Conventions Accepted by Laravel community
Laravel Shorter and More Readable Syntax - WebJourney