#AJAX With Laravel API and More - Learn Laravel Beyond the Limit
Hello, Everyone again with Laravel Advanced Topics Tutorial. Today, I'll show you how we can implement AJAX in our laravel web application.
What is AJAX:
AJAX is Asynchronous JavaScript And XML and AJAX is not a programming language. It's uses some combination of Browser and HTML DOM.
Browser - Send XMLHttpRequest Object to server
HTML DOM - Display data instantly on browser
How to use AJAX in Laravel Application:
AJAX is very simple with Laravel integration. Steps:
- Install Jquery Library
- Make some API's through Laravel
- Call that API inside ajax call. like -
$.ajax({ //.... });
- Send data to server
- Process data in the Server
- Display in the browser after getting the data
Let's start....
For Base Project we'll use this main
branch - https://github.com/ManiruzzamanAkash/Laravel-Advanced-Topics
Where already - We have a Post model and seeder setup
What we'll do today with AJAX example:
- Display all the comments through AJAX
- Send a Comment to the server through AJAX
- Display Validation on the Browser DOM
- Refresh data with Reload after creating Comment
- & Many more concepts...
Create New Model, Migration, Seeder for Post Comment
Create Migration and model
php artisan make:model Comment -m
In migration file - Just add a comment and post_id field as new.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateCommentsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('comments', function (Blueprint $table) {
$table->id();
$table->text('comment');
$table->foreignId('post_id')
->constrained()
->onUpdate('cascade')
->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('comments');
}
}
In model - Models/Comment.php
file just implement basic fillable, as we'll create comment later.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
use HasFactory;
protected $fillable = ['comment', 'post_id'];
}
Also make Post model relationed with Comment model - Post has Many comments. 1 to Many relationship using Eloquent.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasFactory;
public function comments()
{
return $this->hasMany(Comment::class);
}
}
In factories file - database/factories
<?php
namespace Database\Factories;
use App\Models\Comment;
use App\Models\Post;
use Illuminate\Database\Eloquent\Factories\Factory;
class CommentFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = Comment::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
$post_ids = Post::pluck('id')->toArray();
return [
'comment' => $this->faker->text(),
'post_id' => $post_ids[array_rand($post_ids)]
];
}
}
Then setup is done. Just run the command to migrate the seeder with fresh migration -
php artisan migrate:fresh --seed
So, our posts and comments table will be all set and ready to start view post on browser using just Laravel.
Add Routes: in
routes/web.php
<?php
use App\Http\Controllers\PostsController;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| 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('/', [PostsController::class, 'index'])->name('index');
Route::get('/{slug}', [PostsController::class, 'show'])->name('index.show');
In PostsController: Just add two routes functionality
<?php
namespace App\Http\Controllers;
use App\Models\Post;
class PostsController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$posts = Post::with('comments')->paginate(20);
return view('index', compact('posts'));
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
$post = Post::find($id);
return view('show', compact('post'));
}
}
We'll create a main.js file now inside public/js/main.js
Now - Files would be -
Posts List:
views/index.blade.php
-
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
<title>AJAX Example</title>
</head>
<body>
<div class="row justify-content-center">
<div class="col-md-8 mt-5">
<h2>Posts</h2>
@foreach ($posts as $post)
<div class="card card-body mt-2">
<h2> {{ $post->title }} </h2>
<div>
{!! $post->description !!}
</div>
<a href="{{ route('index.show', $post->id) }}">
View
</a>
</div>
@endforeach
</div>
</div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-b5kHyXgcpbZJO/tY9Ul7kGkf1S0CWuKcCD38l8YkeH8z8QjE0GmW1gYU5S9FOnJ0" crossorigin="anonymous">
</script>
</body>
</html>
Post Detail would be -
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
integrity="sha256-eZrrJcwDc/3uDhsdt61sL2oOBY362qM3lon1gyExkL0=" crossorigin="anonymous" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
<title>AJAX Example</title>
</head>
<body>
<div class="container row justify-content-center mb-5" id="post-detail" data-post-id="{{ $post->id }}">
<div class="col-md-8 mt-5 card card-body">
<h2>{{ $post->title }}</h2>
<div>
{!! $post->description !!}
</div>
</div>
<div class="mt-2">
<h3>Comments</h3>
<div id="post-comments">
Loading Comments...
<i class="fa fa-spin fa-spinner" aria-hidden="true"></i>
</div>
<h3 class="mt-5">New Comment</h3>
<div class="alert alert-success visually-hidden" id="successMessage">Comments saved successfully !!</div>
<form action="post" id="comment-submit-form">
@csrf
<input type="hidden" name="post_id" id="post-id-comment" type="hidden" value="{{ $post->id }}">
<textarea name="comment" id="comment-input" cols="30" rows="4" class="form-control"
placeholder="Enter your comment message in 500 characters"></textarea>
<div id="comment-errors-data" class="text-danger"></div>
<br>
<button class="btn btn-success" type="submit" id="comment-submit-button">
Save
</button>
</form>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-b5kHyXgcpbZJO/tY9Ul7kGkf1S0CWuKcCD38l8YkeH8z8QjE0GmW1gYU5S9FOnJ0" crossorigin="anonymous">
</script>
<script src="{{ asset('js/main.js') }}"></script>
<script>
// getCommentsOfPosts({{ $post->id }});
</script>
</body>
</html>
API Routes:
routes/api.php
<?php
use App\Http\Controllers\CommentsController;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
Route::get('/comments/{id}', [CommentsController::class, 'index'])->name('comments.index');
Route::post('/comments/{id}', [CommentsController::class, 'store'])->name('comments.store');
CommentsController to handle API's - app\Http\Controllers\CommentsController.php
<?php
namespace App\Http\Controllers;
use App\Models\Comment;
use Illuminate\Http\Request;
class CommentsController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index($id)
{
$comments = Comment::where('post_id', $id)->orderBy('id', 'desc')->get();
return view('templates.comments', compact('comments'));
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$request->validate(
[
'comment' => 'required'
],
[
'comment.required' => 'Please give comment'
]
);
$comment = Comment::create([
'comment' => $request->comment,
'post_id' => $request->post_id
]);
return $comment;
}
}
Add templates view for getting comments- in templates/comments.blade.php
@foreach ($comments as $comment)
<div class="card card-body m-2">
{{ $comment->comment }}
<p>
<span class="badge badge-info">at {{ $comment->created_at->diffForHumans() }}</span>
</p>
</div>
@endforeach
@if (!count($comments))
<div class="bg-warning p-4">
No Comments found...
</div>
@endif
Main.js File for ajax actions -
$(document).ready(function () {
const post_id = $("#post-detail").attr("data-post-id");
getCommentsOfPosts(post_id)
$("#comment-submit-form").submit(function(e){
e.preventDefault();
const formData = $(this);
const submitButton = $("#comment-submit-button");
const post_id = $("#post-id-comment").val();
submitButton.html('Saving....<i class="fa fa-spin fa-spinner" aria-hidden="true"></i>');
$.ajax({
method: "POST",
url: "/api/comments/" + post_id,
data: formData.serialize(),
success: (result) => {
submitButton.html('Save');
$("#comment-errors-data").html('');
$("#comment-input").val('');
$("#successMessage").removeClass('visually-hidden');
getCommentsOfPosts(post_id);
},
error: (error) => {
if(error.status === 422) { // "Unprocessable Entity" - Form data invalid
$("#successMessage").addClass('visually-hidden');
var message = error.responseJSON.errors ? error.responseJSON.errors.comment ? error.responseJSON.errors.comment[0] : '' : '';
$("#comment-errors-data").html(message);
submitButton.html('Save');
}
}
});
});
});
function getCommentsOfPosts(post_id) {
if( typeof post_id !== 'undefined' && post_id !== '' && !isNaN(post_id)) {
$.ajax({
method: "GET",
url: "/api/comments/" + post_id,
success: (result) => {
$("#post-comments").html(result);
},
error: (error) => {
alert('Something went wrong to fetch datas...');
}
});
}
}
function getPosts() {
$.ajax({
method: "GET",
url: "/api/posts",
success: (result) => {
$("#posts").html(result);
},
error: (error) => {
alert('Something went wrong to fetch datas...');
}
});
}
It's done.
- Lets check in browser with some posts lists
- In detail posts, comments will be loaded in frontend part
- Someone can create comment instantly with comment reloading...
Thanks for viewing the Laravel ajax implementation way.
Popular Tutorials
All Tutorials in this playlist
Popular Tutorials
Categories
-
Artificial Intelligence (AI)
11
-
Bash Scripting
1
-
Bootstrap CSS
0
-
C Programming
14
-
C#
0
-
ChatGPT
1
-
Code Editor
2
-
Computer Engineering
3
-
CSS
28
-
Data Structure and Algorithm
18
-
Design Pattern in PHP
2
-
Design Patterns - Clean Code
1
-
E-Book
1
-
Git Commands
1
-
HTML
19
-
Interview Prepration
2
-
Java Programming
0
-
JavaScript
12
-
Laravel PHP Framework
37
-
Mysql
1
-
Node JS
1
-
Online Business
0
-
PHP
28
-
Programming
8
-
Python
12
-
React Js
19
-
React Native
1
-
Redux
2
-
Rust Programming
15
-
SEO - Search Engine Optimization
1
-
Tailwind CSS
1
-
Typescript
10
-
Uncategorized
0
-
Vue JS
1
-
Windows Operating system
1
-
Woocommerce
1
-
WordPress Development
2
Tags
- Artificial Intelligence (AI)
- Bash Scripting
- Business
- C
- C Programming
- C-sharp programming
- C++
- Code Editor
- Computer Engineering
- CSS
- Data Structure and Algorithm
- Database
- Design pattern
- Express JS
- git
- Git Commands
- github
- HTML
- Java
- JavaScript
- Laravel
- Mathematics
- MongoDB
- Mysql
- Node JS
- PHP
- Programming
- Python
- React Js
- Redux
- Rust Programming Language
- SEO
- TypeScript
- Vue JS
- Windows terminal
- Woocommerce
- WordPress
- WordPress Plugin Development