You can use Ajax in PHP applications to handle form requests asynchronously. Ajax is used with JavaScript and jQuery to complete the form request without refreshing the page. You can use Ajax in the Laravel application to handle the form as well. Ajax supports different types of request types such as GET, POST, PUT, DELETE, etc. It works like a charm to handle the form data internally in the API call. It is a technique so, it doesn’t need any dependency apart from jQuery. In this post, we will be implementing Ajax CRUD in Laravel 10.
Today, in this post, we are going to build Ajax CRUD Application as shown below.
You can check the todo detail by clicking on the View option.
Similarly, there is an Edit option. By clicking on this option, you can open the todo in edit mode. Then from here, you will be able to update the todo.
So, let’s dive into this Ajax CRUD application in Laravel 10.
Prerequisites
We are going to implement Ajax CRUD in Laravel 10. Hence, you need a Laravel 10 application. Laravel 10 requires the below tools and configurations.
- PHP >=8.1
- Composer
- Apache/Nginx Server
- VS Code Editor (Optional)
- MySQL (version > 5)
Once, you are done with the above requirement, let’s have a Laravel 10 project.
How to Validate a Form Using Form Validator in Laravel 10
Create New Project For Ajax CRUD in Laravel 10
In order to create a new application in Laravel 10, you need to hit the below command in the terminal.
composer create-project --prefer-dist laravel/laavel ajax-crud
Once, you installed Laravel 10, let’s connect it to a database.
Create and Configure Database
For the database configuration in the Laravel project, navigate to the .env file available in the root of the project folder. Then update the database credentials as shown below.
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=ajax_crud
DB_USERNAME=root
DB_PASSWORD=root
The database configuration is done now.
In the next step, you need to create a Model and Migration for having a table.
Create a Model and Migration For CRUD Application Using Ajax
In order to create a model and migration, you can run the below command in the terminal.
php artisan make:model Todo -mc
In the above command, I have added one additional flag for the controller. So, it will create a controller as well along with the Model and Migration.
Next, you need to add the schema in the created migration.
<?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('todos', function (Blueprint $table) {
$table->id();
$table->string('title')->nullable();
$table->string('description')->nullable();
$table->boolean('is_completed')->default(false);
$table->boolean('is_deleted')->default(false);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('todos');
}
};
In the next step, you need to set the fillable property in the Todo model. Let’s update that.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Todo extends Model
{
use HasFactory;
protected $fillable = [
'title',
'description',
'is_completed',
'is_deleted'
];
}
After setting up the fillable property in the model, you need to migrate the table using the below command.
php artisan migrate
Now, the table is migrated. So, we can move to the next step of the CRUD Application.
How to Create a CRUD Application in Laravel 10 For Beginners
Create Functionality For Ajax CRUD in Laravel 10
At the very first step of the functionality, navigate to the TodoController and add the below functions.
<?php
namespace App\Http\Controllers;
use App\Models\Todo;
use Illuminate\Http\Request;
class TodoController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
try {
$todos = Todo::all();
return view('index', compact('todos'));
} catch (Exception $e) {
Log::error($e->getMessage());
}
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
try {
$todo = Todo::updateOrCreate(
[
'id' => $request->todoId
],
[
'title' => $request->title,
'description' => $request->description
]
);
if ($todo) {
return response()->json(['status' => 'success', 'data' => $todo]);
}
return response()->json(['status' => 'failed', 'message' => 'Failed! Todo not created']);
} catch (Exception $e) {
Log::error($e->getMessage());
return response()->json(['status' => 'failed', 'message' => $e->getMessage()]);
}
}
/**
* Display the specified resource.
*/
public function show(Todo $todo)
{
try {
if ($todo) {
return response()->json(['status' => 'success', 'data' => $todo]);
}
return response()->json(['status' => 'failed', 'message' => 'No todo found']);
} catch (Exception $e) {
Log::error($e->getMessage());
return response()->json(['status' => 'failed', 'message' => $e->getMessage()]);
}
}
/**
* Remove the specified resource from storage.
*/
public function destroy(Todo $todo)
{
try {
if ($todo) {
$todo->delete();
return response()->json(['status' => 'success', 'data' => $todo, 'message' => 'Todo list deleted successfully']);
}
return response()->json(['status' => 'success', 'message' => 'Todo list not found']);
} catch (Exception $e) {
Log::error($e->getMessage());
return response()->json(['status' => 'failed', 'message' => $e->getMessage()]);
}
}
}
After adding the functionalities, you need to add a route as well.
Add Resource Route in Laravel 10
We created the resource route for the TodoController. Therefore, you will need to add a resource route for this. Hence, you can add the route as shown below.
<?php
use App\Http\Controllers\TodoController;
use Illuminate\Support\Facades\Route;
Route::resource('todos', TodoController::class);
Lastly, you need to create a couple of Views for rendering the Form and the Todos list.
Laravel 10 Released – Check Out Amazing Features of Laravel 10
Create Views For Ajax CRUD in Laravel 10
We are going to implement Ajax CRUD. So, you will have to create these two views-
- master.blade.php
- index.blade.php
In the master view, we will be loading Bootstrap CSS and some script files. As we are implementing Ajax CRUD in Laravel, so, for handling Ajax, I will be using jQuery.
For that, simply create a script.js file in the public/assets folder inside the project.
Then add the below script inside it.
$.ajaxSetup({
headers: {
"X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"),
},
});
$(document).ready(function () {
// create todo
$("#create-todo-btn").click(function () {
$(".error").remove();
$("#todoId").remove();
$("#todo-modal #modal-title").text("Create Todo");
$("#todo-form")[0].reset();
$("#todo-modal").modal("toggle");
});
// form validate and submit
$("#todo-form").validate({
rules: {
title: "required",
description: "required",
},
messages: {
title: "Please enter the title",
description: "Please enter the description",
},
submitHandler: function (form) {
const id = $("input[name=todo]").val();
const formData = $(form).serializeArray();
$.ajax({
url: "todos",
type: "POST",
data: formData,
success: function (response) {
if (response && response.status === "success") {
// clear form
$("#todo-form")[0].reset();
// toggle modal
$("#todo-modal").modal("toggle");
$("#todo-table p").empty();
const data = response.data;
if (id) {
$("#todo_" + id + " td:nth-child(2)").html(
data.title
);
$("#todo_" + id + " td:nth-child(3)").html(
data.description
);
} else {
$("#todo-table").prepend(`<tr id=${
"todo_" + data.id
}><td>${data.id}</td><td>${data.title}</td><td>${
data.description
}</td><td>${
data.is_completed === 1 ? "Yes" : "No"
}</td><td>
<a href="javascript:void(0)" data-id=${
data.id
} title="View" class="btn btn-sm btn-info btn-view"> View </a>
<a href="javascript:void(0)" data-id=${
data.id
} title="Edit" class="btn btn-sm btn-success btn-edit"> Edit </a>
<a href="javascript:void(0)" data-id=${
data.id
} title="Delete" class="btn btn-sm btn-danger btn-delete"> Delete </a></td></tr>`);
}
}
},
});
},
});
});
// view button click
$(".btn-view").click(function () {
const id = $(this).data("id");
$("label.error").remove();
$("input[name=title]").removeClass("error");
$("textarea[name=description]").removeClass("error");
$("input[name=title]").attr("disabled", "disabled");
$("textarea[name=description]").attr("disabled", "disabled");
$("#todo-modal button[type=submit]").addClass("d-none");
$.ajax({
url: `todos/${id}`,
type: "GET",
success: function (response) {
if (response && response.status === "success") {
const data = response.data;
$("#todo-modal #modal-title").text("Todo Detail");
$("#todo-modal input[name=title]").val(data.title);
$("#todo-modal textarea[name=description]").val(
data.description
);
$("#todo-modal").modal("toggle");
}
},
});
});
// edit button click
$(".btn-edit").click(function () {
const id = $(this).data("id");
$("label.error").remove();
$("#status-drodown").remove();
$("input[name=title]").removeClass("error");
$("input[name=title]").after(
'<input type="hidden" name="todoId" value="' + id + '" />'
);
$("textarea[name=description]").removeClass("error");
$("input[name=title]").removeAttr("disabled");
$("textarea[name=description]").removeAttr("disabled");
$("#todo-modal button[type=submit]").removeClass("d-none");
$.ajax({
url: `todos/${id}`,
type: "GET",
success: function (response) {
if (response && response.status === "success") {
const data = response.data;
$("#todo-modal #modal-title").text("Update Todo");
$("#todo-modal input[name=title]").val(data.title);
$("#todo-modal textarea[name=description]").val(data.description);
const selectDropdown = `<div id="status-drodown" class="form-group my-3"><label for="description"> Completed </label><select class="form-select"><option value="1" ${data.is_completed === 1 ? 'selected' : ''}>Yes</option><option value="0" ${data.is_completed === 0 ? 'selected' : ''}>No</option></select></div>`;
$("#todo-modal textarea[name=description]").after(selectDropdown);
$("#todo-modal").modal("toggle");
}
},
});
});
// delete button click
$(".btn-delete").click(function () {
const id = $(this).data("id");
if (id) {
const result = window.confirm("Do you want to delete?");
if (result) {
$.ajax({
url: `todos/${id}`,
type: "DELETE",
success: function (response) {
if (response && response.status === "success") {
const data = response.data;
$(`#todo_${data.id}`).remove();
}
},
});
} else {
console.log("error", "Todo not found");
}
}
});
Now, it’s time to add blade snippets. So, add them one by one as shown below.
<!doctype html>
<html lang="en">
<head>
<title>Laravel 10 Ajax CRUD Application @yield('title')</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<meta name="csrf-token" content="{{ csrf_token() }}"/>
<style>
.error {
color: #ff0000;
}
</style>
</head>
<body>
<div class="container py-5">
@yield('content')
</div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"
integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js"
integrity="sha384-IQsoLXl5PILFhosVNubq5LC7Qb9DXgDA9i+tQ8Zj3iwWAwPtgFTxbJ8NT4GN1R8p" crossorigin="anonymous">
</script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js"
integrity="sha384-IQsoLXl5PILFhosVNubq5LC7Qb9DXgDA9i+tQ8Zj3iwWAwPtgFTxbJ8NT4GN1R8p" crossorigin="anonymous">
</script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.min.js"
integrity="sha384-cVKIPhGWiC2Al4u+LWgxfKTRIcfu0JTxR+EQDz/bgldoEyl4H0zUF0QKbrJ0EcQF" crossorigin="anonymous">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.3/jquery.validate.min.js"
integrity="sha512-37T7leoNS06R80c8Ulq7cdCDU5MNQBwlYoy1TX/WUsLFC2eYNqtKlV0QjH7r8JpG/S0GUMZwebnVFLPd6SU5yg=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="{{ asset('assets/script.js') }}"></script>
</body>
</html>
At last, we have the index blade in which, we will have Todos list. Also, from there we can create and manage the Todo list.
@extends('master')
@section('content')
@section('title') | Todos Listing @endsection
<div class="row">
<div class="col-xl-8 col-lg-8 text-end">
<h3 class="text-end fw-bold"> Laravel 10 Ajax CRUD For Todo App </h3>
</div>
<div class="col-xl-4 col-lg-4 text-end">
<a href="javascript:void(0)" id="create-todo-btn" class="btn btn-primary"> Add Todo </a>
</div>
</div>
<div class="card my-3">
<table class="table table-striped" id="todo-table">
<thead class="bg-secondary text-light">
<tr>
<th>Id</th>
<th width="20%">Title</th>
<th width="45%">Description</th>
<th width="15%">Completed</th>
<th width="20%">Action</th>
<tr>
</thead>
<tbody>
@forelse ($todos as $todo)
<tr id="todo_{{ $todo->id }}">
<td>{{ $todo->id }}</td>
<td>{{ $todo->title }}</td>
<td>{{ $todo->description }}</td>
<td>{{ $todo->is_completed == 1 ? 'Yes' : 'No' }}</td>
<td>
<a href="javascript:void(0)" data-id="{{$todo->id}}" title="View" class="btn btn-sm btn-info btn-view"> View </a>
<a href="javascript:void(0)" data-id="{{$todo->id}}" title="Edit" class="btn btn-sm btn-success btn-edit"> Edit </a>
<a href="javascript:void(0)" data-id="{{$todo->id}}" title="Delete" class="btn btn-sm btn-danger btn-delete"> Delete </a>
</td>
</tr>
@empty
<tr>
<td colspan="5">
<p class="text-danger text-center fw-bold"> No todos found! </p>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
{{-- Add/Edit Todo modal --}}
<div class="modal fade" id="todo-modal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1"
aria-labelledby="todoModal" aria-hidden="true">
<div class="modal-dialog">
<form action="{{ route('todos.store') }}" id="todo-form" method="post">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="modal-title">Create Todo</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
@csrf
<div class="card">
<div class="card-body">
<div class="form-group my-3">
<label for="title"> Title </label>
<input type="text" required name="title" id="title"
class="form-control" placeholder="Title" />
</div>
<div class="form-group my-3">
<label for="description"> Description </label>
<textarea name="description" required id="description" class="form-control" placeholder="Description"></textarea>
</div>
</div>
</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">Save</button>
</div>
</div>
</form>
</div>
</div>
@endsection
That’s it for the functionality. Now, it’s result time to check what we have created.
So, run the application and check the result.
Final Words
We have used Ajax for creating a basic Todo application basically a CRUD application. We handled GET, POST, and DELETE requests to handle the form data. I hope this post will help you in building any Ajax based CRUD application.
Leave a Reply