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:

  1. Install Jquery Library
  2. Make some API’s through Laravel
  3. Call that API inside ajax call. like – $.ajax({ //.... });
  4. Send data to server 
  5. Process data in the Server
  6. 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:

  1. Display all the comments through AJAX
  2. Send a Comment to the server through AJAX
  3. Display Validation on the Browser DOM
  4. Refresh data with Reload after creating Comment
  5. & Many more concepts…

Create New Model, Migration, Seeder for Post Comment

Create Migration and modelphp artisan make:model Comment -m

Copy

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'); } }

Copy

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']; }

Copy

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); } }

Copy

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)] ]; } }

Copy

Then setup is done. Just run the command to migrate the seeder with fresh migration – php artisan migrate:fresh --seed

Copy

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');

Copy

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')); } }

Copy


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>

Copy

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>

Copy

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');

Copy

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; } }

Copy

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

Copy

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...'); } }); }

Copy

It’s done.

  1. Lets check in browser with some posts lists
  2. In detail posts, comments will be loaded in frontend part
  3. Someone can create comment instantly with comment reloading…

Thanks for viewing the Laravel ajax implementation way.

Fonte: https://devsenv.com/tutorials/ajax-with-laravel-api-and-more-learn-laravel-beyond-the-limit

Please follow and like us:
Pin Share

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

RSS
Follow by Email
WP Radio
WP Radio
OFFLINE LIVE