Ajax is a web development technique mainly used to synchronize the data without loading the page. This is a unique feature that feels us a single-page application. The Ajax works with the data without changing any behavior. Only it prevents the page from refreshing after the event is fired. This is very helpful while working on PHP applications. Today, we will use Ajax in Laravel 9 for creating a CRUD application. We will use jQuery for handling the events.
Let’s see what we are going to build in this post.
We will list out all the posts. If there is no post then it will show the message.
You can add a new post by clicking on the Create Post button.
There will be a form validation. I will use jQuery Validator for that.
On submit, if the post is created then it will close the modal and refresh the table automatically.
There will be a view, edit, and delete action. On View, it will open the Post in the read-only mode.
On Edit, it will open the post in Edit mode. You can update the content.
After the update, it will close the modal and refresh the table rows.
Similarly, the delete action will prompt the confirmation before deleting. On successful delete, it will remove the data from the database and this HTML table as well.
So, we will cover all the above functionalities in this post. Hence, let’s proceed to the post.
How to Upload Multiple Files in Laravel 9 with Validation
Prerequisites
Before creating the Laravel 9 application, please make sure of the below configuration.
- PHP >=8.0.2
- Composer
- Apache/Nginx Server
- VS Code Editor (Optional)
- MySQL (version > 5)
Create App For Laravel 9 Ajax CRUD
This step is not recommended if you already have the project setup. If not then create the application using the below command.
composer create-project --prefer-dist laravel/laravel blog
Let the installation finish and then we will move to the next step.
How to Upload File in Laravel 9 With Validation
Configure Database For Laravel 9 Application
Create a database and navigate to the root of the project directory. Find the .env file and configure the database as shown below. Replace your credentials in the database option.
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=DATABASE_NAME
DB_USERNAME=DATABASE_USERNAME
DB_PASSWORD=DATABASE_PASSWORD
Next, you have to create a model, a migration, and a controller.
Upload Multiple Images in Laravel 9 with Validation
Create a Model, Migration, and Controller
We will create a resource controller so that this will have the default CRUD methods.
php artisan make:model Post -mcr
After creating the files, let’s start with the migration file. Open the migration and add the below snippets.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title')->nullable();
$table->text('description')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('posts');
}
};
We have added a few fields to the table. Now, run the migration to have a table.
php artisan migrate
Next, you have to add the mass assignment to the Model.
How to Upload Image in Laravel 9 with Validation
Add Mass Assignment in Laravel 9 Model
Navigate to the model and add the fillable property as shown below.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasFactory;
protected $fillable = [
'title',
'description'
];
}
That’s it for this. Now, move to the controller for implementing the functionalities.
Laravel 9 Ajax CRUD Functionality
For Ajax CRUD operations, you will have to add the CRUD functionality to the controller. Therefore add the below code.
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$posts = Post::orderBy('id', 'desc')->get();
return view('posts.index', compact('posts'));
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$post = Post::updateOrCreate(
[
'id' => $request->postId
],
[
'title' => $request->title,
'description' => $request->description
]
);
if ($post) {
return response()->json(['status' => 'success', 'data' => $post]);
}
return response()->json(['status' => 'failed', 'message' => 'Failed! Post not created']);
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show(Post $post)
{
if ($post) {
return response()->json(['status' => 'success', 'data' => $post]);
}
return response()->json(['status' => 'failed', 'message' => 'No post found']);
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy(Post $post)
{
$post->delete();
return response()->json(['status' => 'success', 'data' => $post]);
}
}
Respectively you will need to add the routes.
Form Validation in Laravel 9 with Custom Error Messages
Add Routes For Laravel 9 Ajax CRUD
Navigate to the web.php and add the below routes.
<?php
use App\Http\Controllers\PostController;
use Illuminate\Support\Facades\Route;
Route::resource('posts', PostController::class);
Next, you have to create the views for data and form handling.
Create Views For Ajax CRUD
Create the following blade file inside the views folder.
- master.blade.php
- index.blade.php
After creating the blades file, let’s start by adding the master layout in the master.blade.php file.
<!doctype html>
<html lang="en">
<head>
<title>Laravel 9 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: #ca0505;
}
</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/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/js/script.js') }}"></script>
</body>
</html>
In the footer, I have added a script for AJAX handling. So, for that, I have created a separate file with the name script.js inside the public folder.
@extends('posts.master')
@section('content')
@section('title') | Posts Listing @endsection
<div class="row">
<div class="col-xl-9 col-lg-9 col-md-9 col-12">
<h3 class="text-center"> Laravel 9 Ajax CRUD </h3>
</div>
<div class="col-xl-3 col-lg-3 col-md-3 col-sm-12 text-end">
<a href="javascript:void(0)" id="create-post-btn" class="btn btn-primary"> Create Post </a>
</div>
</div>
<div class="card my-3">
<table class="table" id="postsTable">
<thead>
<tr>
<th width="10%">Id</th>
<th width="20%">Title</th>
<th width="30%">Description</th>
<th width="20%">Action</th>
<tr>
</thead>
<tbody>
@forelse ($posts as $post)
<tr id="post_{{$post->id}}">
<td>{{ $post->id }}</td>
<td>{{ $post->title }}</td>
<td>{{ $post->description }}</td>
<td>
<a href="javascript:void(0)" data-id="{{$post->id}}" title="View" class="btn btn-sm btn-info btn-view"> View </a>
<a href="javascript:void(0)" data-id="{{$post->id}}" title="Edit" class="btn btn-sm btn-success btn-edit"> Edit </a>
<a href="javascript:void(0)" data-id="{{$post->id}}" title="Delete" class="btn btn-sm btn-danger btn-delete"> Delete </a>
</td>
</tr>
@empty
<tr>
<td colspan="4">
<p class="text-danger text-center"> No post found! </p>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
<!-- modal -->
<div class="modal fade" id="postModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content ">
<form method="post" id="postForm">
<div class="modal-header">
<h5 class="modal-title" id="modalTitle"> AJAX CRUD Application</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label for="title" class="form-label">Title</label>
<input type="text" name="title" class="form-control" id="title" placeholder="Post Title">
</div>
<div class="mb-3">
<label for="description" class="form-label">Body</label>
<textarea class="form-control" name="description" placeholder="Description" id="description" rows="3"></textarea>
</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>
</form>
</div>
</div>
</div>
@endsection
Add the below snippet in the script.js file.
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$(document).ready(function () {
// create post
$('#create-post-btn').click(function() {
$('.error').remove();
$('#postId').remove();
$('#postModal #modalTitle').text('Create Post');
$('#postForm')[0].reset();
$('#postModal').modal('toggle');
});
// form validate and submit
$('#postForm').validate({
rules: {
title: 'required',
description: 'required',
},
messages: {
title: 'Please enter the title',
description: 'Please enter the description',
},
submitHandler: function(form) {
const id = $('input[name=postId]').val();
const formData = $(form).serializeArray();
$.ajax({
url: 'posts',
type: 'POST',
data: formData,
success: function(response) {
if (response && response.status === 'success') {
// clear form
$('#postForm')[0].reset();
// toggle modal
$('#postModal').modal('toggle');
$('#postsTable p').empty();
const data = response.data;
if (id) {
$("#post_"+id+" td:nth-child(2)").html(data.title);
$("#post_"+id+" td:nth-child(3)").html(data.description);
}
else {
$('#postsTable').prepend(`<tr id=${'post_'+data.id}><td>${data.id}</td><td>${data.title}</td><td>${data.description}</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');
$('#postModal button[type=submit]').addClass('d-none');
$.ajax({
url: `posts/${id}`,
type: 'GET',
success: function(response) {
if (response && response.status === 'success') {
const data = response.data;
$('#postModal #modalTitle').text('Post Detail');
$('#postModal input[name=title]').val(data.title);
$('#postModal textarea[name=description]').val(data.description);
$('#postModal').modal('toggle');
}
}
})
});
// edit button click
$('.btn-edit').click(function() {
const id = $(this).data('id');
$('label.error').remove();
$('input[name=title]').removeClass('error');
$('input[name=title]').after('<input type="hidden" name="postId" value="'+id+'" />')
$('textarea[name=description]').removeClass('error');
$('input[name=title]').removeAttr('disabled');
$('textarea[name=description]').removeAttr('disabled');
$('#postModal button[type=submit]').removeClass('d-none');
$.ajax({
url: `posts/${id}`,
type: 'GET',
success: function(response) {
if (response && response.status === 'success') {
const data = response.data;
$('#postModal #modalTitle').text('Update Post');
$('#postModal input[name=title]').val(data.title);
$('#postModal textarea[name=description]').val(data.description);
$('#postModal').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: `posts/${id}`,
type: 'DELETE',
success: function(response) {
if (response && response.status === 'success') {
const data = response.data;
$(`#post_${data.id}`).remove();
}
}
});
}
else {
console.log('error', 'Post not found');
}
}
});
That’s it for the functionalities of Ajax CRUD. Now, run the application to see the result.
Conclusion
We covered the Ajax form handling in Laravel 9. We created a demo app for the blog using the CRUD operations. I hope you will find helpful to this post.
Leave a Reply