How to Make HTTP Requests with AJAX in Laravel 8 and Bootstrap

This step by step Laravel 8 AJAX guide helps you how to make HTTP requests (GET & POST) in a Laravel application.

AJAX stands for Asynchronous JavaScript And XML, and it is useful in many ways. You can update a web page without reloading the web page, make HTTP requests for Sending, Getting and Receiving the data from the server.

In this Laravel AJAX example, you will create a basic application and understand the idea of AJAX implementation in laravel project notwithstanding you will also ascertain how should AJAX is used to send and receive data from the server.

Generate Laravel App

Initiate the application installation process:

composer create-project laravel/laravel laravel-ajax-example --prefer-dist

Add Database Credentials

Add database name, username, password in .env file.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=db
DB_USERNAME=root
DB_PASSWORD=

If working locally then start local development server either MAMP or XAMPP could be the best option:

Paste the following line right after the database configuration inside the .env.

Compose Model and Migration

Table values are defined in laravel model and migration, on top of that, we need to require these column properties for database interaction simultaneously to handle the AJAX request.

For running migration adjoin the following values in migrations/timestamp_create_products_table.php file:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateProductsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('products', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('details');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('products');
    }
}

Run command to generate a Model:

php artisan make:model Product -m

Insert Product table’s column values in app/Models/Product.php file:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    use HasFactory;
    protected $fillable = ['name', 'details'];
}

Now, you can run migration from console:

php artisan migrate

Develop Controller

Controller is the file which contains the core logic of particular functionality, so run command to generate a new controller.

php artisan make:controller ProductController

Add the given below code in app/Http/Controllers/ProductController.php:

<?php

namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Product;
use Response;

class ProductController extends Controller
{

    public function index()
    {
        $data = Product::all();
        return view('welcome')->with(compact('data'));
    }

    
    public function store(Request $request)
    {
        $items = $request->validate([
            'name' => 'required|max:255',
            'details' => 'required'
        ]);
        
        $products = Product::create($items);

        return Response::json($products);
    }
}

Import product model, this is being used to send and receive the data from the database. The index() method is fetching the products data, whereas store() is adding the product into the database.

Make Routes

You need to create the two routes, one to show the data equally important to store the data in MySQL database with AJAX requests.
Add the code in routes/web.php:

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ProductController;

/*
|--------------------------------------------------------------------------
| 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('/', [ProductController::class, 'index']);

Route::resource('products', ProductController::class);

Create Blade View

Now that you need to create a view of the basic application with Bootstrap, add the given below code in views/layouts/home.blade.php file:

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="csrf-token" content="{{ csrf_token() }}">

        <title>AJAX in Laravel Example</title>

        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
        <!-- Fonts -->
        <link href="https://fonts.googleapis.com/css2?family=Nunito:[email protected];600;700&display=swap" rel="stylesheet">

        <!-- Styles -->
        <style>
            /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}a{background-color:transparent}[hidden]{display:none}html{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}*,:after,:before{box-sizing:border-box;border:0 solid #e2e8f0}a{color:inherit;text-decoration:inherit}svg,video{display:block;vertical-align:middle}video{max-width:100%;height:auto}.bg-white{--bg-opacity:1;background-color:#fff;background-color:rgba(255,255,255,var(--bg-opacity))}.bg-gray-100{--bg-opacity:1;background-color:#f7fafc;background-color:rgba(247,250,252,var(--bg-opacity))}.border-gray-200{--border-opacity:1;border-color:#edf2f7;border-color:rgba(237,242,247,var(--border-opacity))}.border-t{border-top-width:1px}.flex{display:flex}.grid{display:grid}.hidden{display:none}.items-center{align-items:center}.justify-center{justify-content:center}.font-semibold{font-weight:600}.h-5{height:1.25rem}.h-8{height:2rem}.h-16{height:4rem}.text-sm{font-size:.875rem}.text-lg{font-size:1.125rem}.leading-7{line-height:1.75rem}.mx-auto{margin-left:auto;margin-right:auto}.ml-1{margin-left:.25rem}.mt-2{margin-top:.5rem}.mr-2{margin-right:.5rem}.ml-2{margin-left:.5rem}.mt-4{margin-top:1rem}.ml-4{margin-left:1rem}.mt-8{margin-top:2rem}.ml-12{margin-left:3rem}.-mt-px{margin-top:-1px}.max-w-6xl{max-width:72rem}.min-h-screen{min-height:100vh}.overflow-hidden{overflow:hidden}.p-6{padding:1.5rem}.py-4{padding-top:1rem;padding-bottom:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.pt-8{padding-top:2rem}.fixed{position:fixed}.relative{position:relative}.top-0{top:0}.right-0{right:0}.shadow{box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06)}.text-center{text-align:center}.text-gray-200{--text-opacity:1;color:#edf2f7;color:rgba(237,242,247,var(--text-opacity))}.text-gray-300{--text-opacity:1;color:#e2e8f0;color:rgba(226,232,240,var(--text-opacity))}.text-gray-400{--text-opacity:1;color:#cbd5e0;color:rgba(203,213,224,var(--text-opacity))}.text-gray-500{--text-opacity:1;color:#a0aec0;color:rgba(160,174,192,var(--text-opacity))}.text-gray-600{--text-opacity:1;color:#718096;color:rgba(113,128,150,var(--text-opacity))}.text-gray-700{--text-opacity:1;color:#4a5568;color:rgba(74,85,104,var(--text-opacity))}.text-gray-900{--text-opacity:1;color:#1a202c;color:rgba(26,32,44,var(--text-opacity))}.underline{text-decoration:underline}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.w-5{width:1.25rem}.w-8{width:2rem}.w-auto{width:auto}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}@media (min-width:640px){.sm\:rounded-lg{border-radius:.5rem}.sm\:block{display:block}.sm\:items-center{align-items:center}.sm\:justify-start{justify-content:flex-start}.sm\:justify-between{justify-content:space-between}.sm\:h-20{height:5rem}.sm\:ml-0{margin-left:0}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:pt-0{padding-top:0}.sm\:text-left{text-align:left}.sm\:text-right{text-align:right}}@media (min-width:768px){.md\:border-t-0{border-top-width:0}.md\:border-l{border-left-width:1px}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width:1024px){.lg\:px-8{padding-left:2rem;padding-right:2rem}}@media (prefers-color-scheme:dark){.dark\:bg-gray-800{--bg-opacity:1;background-color:#2d3748;background-color:rgba(45,55,72,var(--bg-opacity))}.dark\:bg-gray-900{--bg-opacity:1;background-color:#1a202c;background-color:rgba(26,32,44,var(--bg-opacity))}.dark\:border-gray-700{--border-opacity:1;border-color:#4a5568;border-color:rgba(74,85,104,var(--border-opacity))}.dark\:text-white{--text-opacity:1;color:#fff;color:rgba(255,255,255,var(--text-opacity))}.dark\:text-gray-400{--text-opacity:1;color:#cbd5e0;color:rgba(203,213,224,var(--text-opacity))}}
        </style>

        <style>
            body {
                font-family: 'Nunito';
            }
        </style>
    </head>
    <body class="antialiased mt-5">
        <div class="container">
            <div class="d-flex bd-highlight mb-2">
                <div class="p-2 flex-shrink-0 bd-highlight">
                    <button class="btn btn-primary" id="create-product">
                        Create Product
                    </button>
                </div>
            </div>

            <div>
                <table class="table table-inverse">
                    <thead>
                        <tr>
                            <th>#ID</th>
                            <th>Name</th>
                            <th>Details</th>
                        </tr>
                    </thead>
                    <tbody id="product-list" name="product-list">
                        @foreach ($data as $item)
                        <tr id="product{{$item->id}}">
                            <td>{{$item->id}}</td>
                            <td>{{$item->name}}</td>
                            <td>{{$item->details}}</td>
                        </tr>
                        @endforeach
                    </tbody>
                </table>

                <div class="modal fade" id="openModal" aria-hidden="true">
                    <div class="modal-dialog">
                        <div class="modal-content">
                            <div class="modal-header">
                                <h4 class="modal-title" id="formModalLabel">Create Product</h4>
                            </div>
                            <div class="modal-body">
                                <form id="productForm" name="productForm" class="form-horizontal" novalidate="">
                                    <div class="form-group">
                                        <label>Name</label>
                                        <input type="text" class="form-control" id="name" name="name"
                                                placeholder="Add name" value="">
                                    </div>

                                    <div class="form-group">
                                        <label>Details</label>
                                            <input type="text" class="form-control" id="details" name="details"
                                                placeholder="Add details" value="">
                                    </div>
                                </form>
                            </div>
                            <div class="modal-footer">
                                <button class="btn btn-success btn-block" type="button"  id="add-product" value="add">Add</button>
                                <input type="hidden" id="product_id" name="product_id" value="0">
                            </div>
                        </div>
                    </div>
                </div>

            </div>
        </div>    
    
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
    <script>
        jQuery(document).ready(function($){
            
            jQuery('#create-product').click(function () {
                jQuery('#add-product').val("add");
                jQuery('#productForm').trigger("reset");
                jQuery('#openModal').modal('show');
            });

            // CREATE
            $("#add-product").click(function (event) {
                event.preventDefault();
                $.ajaxSetup({
                    headers: {
                        'X-CSRF-TOKEN': jQuery('meta[name="csrf-token"]').attr('content')
                    }
                });

                var formData = {
                    name: jQuery('#name').val(),
                    details: jQuery('#details').val(),
                };

                var state = jQuery('#add-product').val();
                var type = "POST";
                var product_id = jQuery('#product_id').val();
                var ajaxurl = 'products';
                $.ajax({
                    type: type,
                    url: ajaxurl,
                    data: formData,
                    dataType: 'json',
                    success: function (res) {
                        var products = '<tr id="products' + res.id + '"><td>' + res.id + '</td><td>' + res.name + '</td><td>' + res.details + '</td>';
                        if (state == "add") {
                            jQuery('#prod-list').append(products);
                        } else {
                            jQuery("#products" + product_id).replaceWith(products);
                        }
                        jQuery('#productForm').trigger("reset");
                        jQuery('#openModal').modal('hide')
                    },
                    error: function (res) {
                        console.log(res);
                    }
                }); 
            });
        });
    </script>
    </body>
</html>

Invoke Laravel Ajax Application

The application can be started using following command:

php artisan serve
http://127.0.0.1:8000/products

Summary

The Laravel AJAX example tutorial is completed, now you have a basic idea of how to use AJAX in Laravel to make HTTP requests. Not only – but also communicate with the server having said that this is just the starting and there are multiple things you can try with AJAX.