Contents
Introduction:
Laravel has been the most chosen and known web framework by developers in the market. There are a lot of advantages if you choose Laravel in your next big project. In this blog, You will learn how to develop a Laravel 11 CRUD using AJAX and DataTables by following an easy step-by-step tutorial.
Laravel is a free, open-source PHP Web Framework intended for the development of web applications following the MVC (Model-View-Controller) architectural pattern. Laravel is designed to make developing web apps faster and easier by using built-in features.
DataTables is a jQuery plugin that is a highly flexible tool and adds advanced features to any HTML tables. The main features in Datatables are pagination, sorting, filtering, and server-side processing.
AJAX(Asynchronous JavaScript and XML) is a set of web development techniques that use many web technologies that allow web applications to work asynchronously.
CRUD is an acronym for CREATE, READ, UPDATE, DELETE. The four basic functions in any type of programming. CRUD typically refers to operations performed in a database.
- Create -Generate new record/s.
- Read – Reads or retrieves record/s.
- Update – Modify record/s.
- Delete – Destroy or remove record/s.
Prerequisite:
- Composer
- MySQL
- PHP >= 8.2
Step 1: Install Laravel 11
First, select a folder where you want Laravel to be installed then execute this command on Terminal or CMD to install Laravel 11:
Install via composer:
composer create-project laravel/laravel laravel-11-crud-ajax-datatables
Install via Laravel Install:
laravel new laravel-11-crud-ajax-datatables
Step 2: Install Yajra DataTables
After installing, Open the Laravel app folder and execute this command to install Yajra DataTables:
$ composer require yajra/laravel-datatables-oracle
and register it on the provider on the bootstrap/providers.php file.
bootstrap\providers.php
<?php
return [
App\Providers\AppServiceProvider::class,
Yajra\DataTables\DataTablesServiceProvider::class
];
Then publish it:
php artisan vendor:publish --tag=datatables
Step 3: Set Database Configuration
Open the .env file and set the database configuration:
.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=your database name(laravel_11_ajax_crud_datatables)
DB_USERNAME=your database username(root)
DB_PASSWORD=your database password(root)
Step 4: Create Model and Database Migration
Model – it is a class that represents a database table.
Migration – like version control for the database that allows us to modify and share database schema to your team.
Execute this command on the Terminal or CMD to create a model and migration:
php artisan make:model Project --migration
After this command, you will find one file in this path “database/migrations” and put the code below on the migration file.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('projects', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->text('description');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('projects');
}
};
Run the migration by executing the migrate
Artisan command:
php artisan migrate
Step 5: Create A Resource Controller
Resource Controller is a controller that handles all HTTP request stored by your application.
Execute this command to create a resource controller:
php artisan make:controller ProjectController --api
This command will generate a controller at “app/Http/Controllers/ProjectController.php”. It contains methods for each of the available resource operations. Open the file and insert these codes:
app/Http/Controllers/ProjectController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Project;
use Yajra\DataTables\Facades\DataTables;
class ProjectController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
$projects = Project::query();
return DataTables::of($projects)
->addColumn('action', function ($project) {
$showBtn = '<button ' .
' class="btn btn-outline-info" ' .
' onclick="showProject(' . $project->id . ')">Show' .
'</button> ';
$editBtn = '<button ' .
' class="btn btn-outline-success" ' .
' onclick="editProject(' . $project->id . ')">Edit' .
'</button> ';
$deleteBtn = '<button ' .
' class="btn btn-outline-danger" ' .
' onclick="destroyProject(' . $project->id . ')">Delete' .
'</button> ';
return $showBtn . $editBtn . $deleteBtn;
})
->rawColumns(
[
'action',
])
->make(true);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
request()->validate([
'name' => 'required|max:255',
'description' => 'required',
]);
$project = new Project();
$project->name = $request->name;
$project->description = $request->description;
$project->save();
return response()->json(['status' => "success"]);
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
$project = Project::find($id);
return response()->json(['project' => $project]);
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
request()->validate([
'name' => 'required|max:255',
'description' => 'required',
]);
$project = Project::find($id);
$project->name = $request->name;
$project->description = $request->description;
$project->save();
return response()->json(['status' => "success"]);
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
Project::destroy($id);
return response()->json(['status' => "success"]);
}
}
Step 6: Register a Route
After creating a resource controller, register a resourceful route and register the view route.
routes/web.php
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ProjectController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', function () {
return view('projects');
});
Route::resource('projects', ProjectController::class);
Step 7: Create Blade File
Blade is the simple but powerful templating engine in laravel. blade view files have a .blade.php files extension and usually stores on “resources/views/” folder.
We will use Bootstrap to make our simple CRUD app presentable. Bootstrap is a free and most popular open-source CSS framework for building responsive and mobile-first web projects.
Create a blade file “projects.blade.php” inside this following path “resources/views/”. After creating the blade file, Insert the code below:
resources/views/projects.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<title>Laravel Project Manager</title>
<meta charset="utf-8">
<meta name="csrf-token" content="{{ csrf_token() }}">
<meta name="app-url" content="{{ url('/') }}">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdn.datatables.net/1.10.25/css/dataTables.bootstrap5.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<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>
</head>
<body>
<div class="container">
<h2 class="text-center mt-5 mb-3">Laravel Project Manager</h2>
<div class="card">
<div class="card-header">
<button class="btn btn-outline-primary" onclick="createProject()">
Create New Project
</button>
</div>
<div class="card-body">
<div id="alert-div">
</div>
<table class="table table-bordered" id="projects_table">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th width="240px">Action</th>
</tr>
</thead>
<tbody id="projects-table-body">
</tbody>
</table>
</div>
</div>
</div>
<!-- project form modal -->
<div class="modal" tabindex="-1" role="dialog" id="form-modal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Project Form</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div id="error-div"></div>
<form>
<input type="hidden" name="update_id" id="update_id">
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" id="name" name="name">
</div>
<div class="form-group">
<label for="description">Description</label>
<textarea class="form-control" id="description" rows="3" name="description"></textarea>
</div>
<button type="submit" class="btn btn-outline-primary mt-3" id="save-project-btn">Save Project</button>
</form>
</div>
</div>
</div>
</div>
<!-- view project modal -->
<div class="modal " tabindex="-1" role="dialog" id="view-modal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Project Information</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<b>Name:</b>
<p id="name-info"></p>
<b>Description:</b>
<p id="description-info"></p>
</div>
</div>
</div>
</div>
<script src="https://cdn.datatables.net/1.10.25/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.10.25/js/dataTables.bootstrap5.min.js"></script>
<script type="text/javascript">
$(function() {
var baseUrl = $('meta[name=app-url]').attr("content");
let url = baseUrl + '/projects';
// create a datatable
$('#projects_table').DataTable({
processing: true,
ajax: url,
"order": [[ 0, "desc" ]],
columns: [
{ data: 'name'},
{ data: 'description'},
{ data: 'action'},
],
});
});
function reloadTable()
{
/*
reload the data on the datatable
*/
$('#projects_table').DataTable().ajax.reload();
}
/*
check if form submitted is for creating or updating
*/
$("#save-project-btn").click(function(event ){
event.preventDefault();
if($("#update_id").val() == null || $("#update_id").val() == "")
{
storeProject();
} else {
updateProject();
}
})
/*
show modal for creating a record and
empty the values of form and remove existing alerts
*/
function createProject()
{
$("#alert-div").html("");
$("#error-div").html("");
$("#update_id").val("");
$("#name").val("");
$("#description").val("");
$("#form-modal").modal('show');
}
/*
submit the form and will be stored to the database
*/
function storeProject()
{
$("#save-project-btn").prop('disabled', true);
let url = $('meta[name=app-url]').attr("content") + "/projects";
let data = {
name: $("#name").val(),
description: $("#description").val(),
};
$.ajax({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
url: url,
type: "POST",
data: data,
success: function(response) {
$("#save-project-btn").prop('disabled', false);
let successHtml = '<div class="alert alert-success" role="alert"><b>Project Created Successfully</b></div>';
$("#alert-div").html(successHtml);
$("#name").val("");
$("#description").val("");
reloadTable();
$("#form-modal").modal('hide');
},
error: function(response) {
$("#save-project-btn").prop('disabled', false);
if (typeof response.responseJSON.errors !== 'undefined')
{
let errors = response.responseJSON.errors;
let descriptionValidation = "";
if (typeof errors.description !== 'undefined')
{
descriptionValidation = '<li>' + errors.description[0] + '</li>';
}
let nameValidation = "";
if (typeof errors.name !== 'undefined')
{
nameValidation = '<li>' + errors.name[0] + '</li>';
}
let errorHtml = '<div class="alert alert-danger" role="alert">' +
'<b>Validation Error!</b>' +
'<ul>' + nameValidation + descriptionValidation + '</ul>' +
'</div>';
$("#error-div").html(errorHtml);
}
}
});
}
/*
edit record function
it will get the existing value and show the project form
*/
function editProject(id)
{
let url = $('meta[name=app-url]').attr("content") + "/projects/" + id;
$.ajax({
url: url,
type: "GET",
success: function(response) {
let project = response.project;
$("#alert-div").html("");
$("#error-div").html("");
$("#update_id").val(project.id);
$("#name").val(project.name);
$("#description").val(project.description);
$("#form-modal").modal('show');
},
error: function(response) {
console.log(response.responseJSON)
}
});
}
/*
sumbit the form and will update a record
*/
function updateProject()
{
$("#save-project-btn").prop('disabled', true);
let url = $('meta[name=app-url]').attr("content") + "/projects/" + $("#update_id").val();
let data = {
id: $("#update_id").val(),
name: $("#name").val(),
description: $("#description").val(),
};
$.ajax({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
url: url,
type: "PUT",
data: data,
success: function(response) {
$("#save-project-btn").prop('disabled', false);
let successHtml = '<div class="alert alert-success" role="alert"><b>Project Updated Successfully</b></div>';
$("#alert-div").html(successHtml);
$("#name").val("");
$("#description").val("");
reloadTable();
$("#form-modal").modal('hide');
},
error: function(response) {
$("#save-project-btn").prop('disabled', false);
if (typeof response.responseJSON.errors !== 'undefined')
{
let errors = response.responseJSON.errors;
let descriptionValidation = "";
if (typeof errors.description !== 'undefined')
{
descriptionValidation = '<li>' + errors.description[0] + '</li>';
}
let nameValidation = "";
if (typeof errors.name !== 'undefined')
{
nameValidation = '<li>' + errors.name[0] + '</li>';
}
let errorHtml = '<div class="alert alert-danger" role="alert">' +
'<b>Validation Error!</b>' +
'<ul>' + nameValidation + descriptionValidation + '</ul>' +
'</div>';
$("#error-div").html(errorHtml);
}
}
});
}
/*
get and display the record info on modal
*/
function showProject(id)
{
$("#name-info").html("");
$("#description-info").html("");
let url = $('meta[name=app-url]').attr("content") + "/projects/" + id +"";
$.ajax({
url: url,
type: "GET",
success: function(response) {
let project = response.project;
$("#name-info").html(project.name);
$("#description-info").html(project.description);
$("#view-modal").modal('show');
},
error: function(response) {
console.log(response.responseJSON)
}
});
}
/*
delete record function
*/
function destroyProject(id)
{
let url = $('meta[name=app-url]').attr("content") + "/projects/" + id;
let data = {
name: $("#name").val(),
description: $("#description").val(),
};
$.ajax({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
url: url,
type: "DELETE",
data: data,
success: function(response) {
let successHtml = '<div class="alert alert-success" role="alert"><b>Project Deleted Successfully</b></div>';
$("#alert-div").html(successHtml);
reloadTable();
},
error: function(response) {
console.log(response.responseJSON)
}
});
}
</script>
</body>
</html>
Step 8: Run the Application
After finishing the steps above, you can now run your application by executing the code below:
php artisan serve
After successfully running your app, open this URL in your browser:
http://localhost:8000
Screenshots:
Laravel 11 CRUD Using AJAX And DataTables (project index page):
Laravel 11 CRUD Using AJAX And DataTables (create project form modal):
Laravel 11 CRUD Using AJAX And DataTables (edit project form modal):
Laravel 11 CRUD Using AJAX And DataTables (show project information modal):