Laravel 7 AJAX CRUD App Easy Step-By-Step Tutorial

Laravel 7 AJAX CRUD App Easy Step-By-Step Tutorial

Avatar photoPosted by

Introduction:

In this blog, You will learn how to develop a Laravel 7 AJAX CRUD App by following an easy step-by-step tutorial. But before that let us have an introduction:

Laravel is a free, open-source PHP Web Framework and intended for the development of web applications following the MVC (Model-View-Controller) architectural pattern. Laravel is designed to make developing web apps faster and easier by using the built-in features.

AJAX(Asynchronous JavaScript and XML) is a set of web development techniques that use many web technologies which allow web applications work in asynchronously.

CRUD is an acronym for CREATE, READ, UPDATE, DELETE. The four basic functions in any type of programming. CRUD typically refers to operations performed in a database.

  • Create -Generate new record/s.
  • Read – Reads or retrieve record/s.
  • Update – Modify record/s.
  • Delete – Destroy or remove record/s.

Prerequisite:

Before proceeding on this tutorial, you must have an environment already setup to run and install Laravel. If you haven’t, please do read my blog – How to Install Laravel 7 in Windows with XAMPP and Composer Easy Tutorial.

Step 1: Install Laravel 7 Using Composer

First, select a folder that you want the Laravel to be installed then execute this command on Terminal or CMD to install Laravel 7:

composer create-project --prefer-dist laravel/laravel project-manager "7.*"

Step 2: Set Database Configuration

After installing, Open the Laravel app folder and open the .env file and set database configuration:

.env

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=your database name(project_manager)
DB_USERNAME=your database username(root)
DB_PASSWORD=your database password(root)

Step 3: Create Model and Database Migration

Model – it a class that represents a database table.

Migration – like version control for the database that allows us to modify and share database schema to your team.

Execute this command on the Terminal or CMD to create a model and migration:

php artisan make:model Project --migration

After this command you will find one file in this path “database/migrations” and put the code below on the migration file.

<?php

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

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

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

Run the migration by executing the migrate Artisan command:

php artisan migrate

Step 4: Create A Resource Controller

Resource Controller is a controller that handles all HTTP request stored by your application.

Execute this command to create a resource controller:

php artisan make:controller ProjectController --resource

This command will generate a controller at “app/Http/Controllers/ProjectController.php”. It contains methods for each of the available resource operations. Open the file and insert these codes:

app/Http/Controllers/ProjectController.php

<?php

namespace App\Http\Controllers;

use App\Project;
use Illuminate\Http\Request;

class ProjectController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $projects = Project::get();
        return response()->json(['projects' => $projects]);
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
       
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        request()->validate([
            'name' => 'required|max:255',
            'description' => 'required',
        ]);

        $project = new Project();
        $project->name = $request->name;
        $project->description = $request->description;
        $project->save();
        return response()->json(['status' => "success"]);
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        $project = Project::find($id);
        return response()->json(['project' => $project]);
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        $project = Project::find($id);
        return response()->json(['project' => $project]);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
         request()->validate([
            'name' => 'required|max:255',
            'description' => 'required',
        ]);

        $project = Project::find($id);
        $project->name = $request->name;
        $project->description = $request->description;
        $project->save();
        return response()->json(['status' => "success"]);
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        Project::destroy($id);
        return response()->json(['status' => "success"]);
    }

   
}

Step 5: Register a Route

After creating a resource controller, register a resourceful route and register the view route.

routes/web.php

Route::get('/', function () {
    return view('projects');
});

/*
This single route will create multiple routes to handle the CRUD actions on the resource. 
*/
Route::resource('projects', 'ProjectController');

Step 6: Create Blade File

Blade is the simple but powerful templating engine in laravel. blade view files have a .blade.php files extension and usually stores on “resources/views/” folder.

We will use Bootstrap to make our simple CRUD app presentable. Bootstrap is a free and most popular open-source CSS framework for building responsive and mobile-first web projects.

Create a blade file “projects.blade.php”  inside this following path “resources/views/”. After creating the blade file, Insert the code below:

resources/views/projects.blade.php

<!DOCTYPE html>
<html lang="en">
<head>
  <title>Laravel Project Manager</title>
  <meta charset="utf-8">
  <meta name="csrf-token" content="{{ csrf_token() }}">
  <meta name="app-url" content="{{ url('/') }}">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
</head>
<body>


<div class="container">
    <h2 class="text-center mt-5 mb-3">Laravel Project Manager</h2>
    <div class="card">
        <div class="card-header">
            <button class="btn btn-outline-primary" onclick="createProject()"> 
                Create New Project
            </button>
        </div>
        <div class="card-body">
           	<div id="alert-div">
      		
      		</div>
            <table class="table table-bordered">
            	<thead>
	                <tr>
	                    <th>Name</th>
	                    <th>Description</th>
	                    <th width="240px">Action</th>
	                </tr>
	            </thead>
	            <tbody id="projects-table-body">
	            	
	            </tbody>
                
            </table>
        </div>
    </div>
</div>

<!-- modal for creating and editing function -->
<div class="modal" tabindex="-1" role="dialog" id="form-modal">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Project Form</h5>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">×</span>
        </button>
      </div>
      <div class="modal-body">
      	<div id="error-div"></div>
        <form>
        	<input type="hidden" name="update_id" id="update_id">
            <div class="form-group">
                <label for="name">Name</label>
                <input type="text" class="form-control" id="name" name="name">
            </div>
            <div class="form-group">
                <label for="description">Description</label>
                <textarea class="form-control" id="description" rows="3" name="description"></textarea>
            </div>
         
            <button type="submit" class="btn btn-outline-primary" id="save-project-btn">Save Project</button>
        </form>
      </div>
    </div>
  </div>
</div>

<!-- view record modal -->
<div class="modal" tabindex="-1" role="dialog" id="view-modal">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Project Information</h5>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">×</span>
        </button>
      </div>
      <div class="modal-body">
      	<b>Name:</b>
      	<p id="name-info"></p>
      	<b>Description:</b>
      	<p id="description-info"></p>
      </div>
    </div>
  </div>
</div>

<script type="text/javascript">

	
	showAllProjects();

	/*
		This function will get all the project records
	*/
	function showAllProjects()
	{
		let url = $('meta[name=app-url]').attr("content") + "/projects";
		$.ajax({
	        url: url,
	        type: "GET",
	        success: function(response) {
	            $("#projects-table-body").html("");
	            let projects = response.projects;
	            for (var i = 0; i < projects.length; i++) 
	            {
	            	let showBtn =  '<button ' +
	            						' class="btn btn-outline-info" ' +
	            						' onclick="showProject(' + projects[i].id + ')">Show' +
	            					'</button> ';
	            	let editBtn =  '<button ' +
	            						' class="btn btn-outline-success" ' +
	            						' onclick="editProject(' + projects[i].id + ')">Edit' +
	            					'</button> ';
	            	let deleteBtn =  '<button ' +
	            						' class="btn btn-outline-danger" ' +
	            						' onclick="destroyProject(' + projects[i].id + ')">Delete' +
	            					'</button>';

	            	let projectRow = '<tr>' +
	            						'<td>' + projects[i].name + '</td>' +
	            						'<td>' + projects[i].description + '</td>' +
	            						'<td>' + showBtn + editBtn + deleteBtn + '</td>' +
	            					'</tr>';
	            	$("#projects-table-body").append(projectRow);
	            }

	            
	        },
	        error: function(response) {
	          	console.log(response.responseJSON)
	        }
      	});
	}

	/*
		check if form submitted is for creating or updating
	*/
	$("#save-project-btn").click(function(event ){
		event.preventDefault();
		if($("#update_id").val() == null || $("#update_id").val() == "")
		{
			storeProject();
		} else {
			updateProject();
		}
	})

	/*
		show modal for creating a record and 
		empty the values of form and remove existing alerts
	*/
	function createProject()
	{
		$("#alert-div").html("");
		$("#error-div").html("");	
		$("#update_id").val("");
		$("#name").val("");
		$("#description").val("");
		$("#form-modal").modal('show');	
	}

	/*
		submit the form and will be stored to the database
	*/
	function storeProject()
	{	
		$("#save-project-btn").prop('disabled', true);
		let url = $('meta[name=app-url]').attr("content") + "/projects";
  		let data = {
      		name: $("#name").val(),
      		description: $("#description").val(),
    	};
		$.ajax({
			headers: {
                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
	        },
	        url: url,
	        type: "POST",
	        data: data,
	        success: function(response) {
	        	$("#save-project-btn").prop('disabled', false);
	        	let successHtml = '<div class="alert alert-success" role="alert"><b>Project Created Successfully</b></div>';
	        	$("#alert-div").html(successHtml);
	        	$("#name").val("");
	        	$("#description").val("");
	        	showAllProjects();
	        	$("#form-modal").modal('hide');
	        },
	        error: function(response) {
	        	$("#save-project-btn").prop('disabled', false);

	        	/*
					show validation error
	        	*/
	          	if (typeof response.responseJSON.errors !== 'undefined') 
	          	{
				    let errors = response.responseJSON.errors;
				    let descriptionValidation = "";
				    if (typeof errors.description !== 'undefined') 
	          		{
	          			descriptionValidation = '<li>' + errors.description[0] + '</li>';
	          		}
	          		let nameValidation = "";
				   	if (typeof errors.name !== 'undefined') 
	          		{
	          			nameValidation = '<li>' + errors.name[0] + '</li>';
	          		}
				    
				    let errorHtml = '<div class="alert alert-danger" role="alert">' +
				    					'<b>Validation Error!</b>' +
				  						'<ul>' + nameValidation + descriptionValidation + '</ul>' +
									'</div>';
					$("#error-div").html(errorHtml);		
				}
	        }
      	});
	}


	/*
		edit record function
		it will get the existing value and show the project form
	*/
	function editProject(id)
	{
		let url = $('meta[name=app-url]').attr("content") + "/projects/" + id +"/edit";
		$.ajax({
	        url: url,
	        type: "GET",
	        success: function(response) {
	           	let project = response.project;
	           	$("#alert-div").html("");
	           	$("#error-div").html("");	
				$("#update_id").val(project.id);
				$("#name").val(project.name);
				$("#description").val(project.description);
				$("#form-modal").modal('show');	
	        },
	        error: function(response) {
	          	console.log(response.responseJSON)
	        }
      	});
	}

	/*
		sumbit the form and will update a record
	*/
	function updateProject()
	{
		$("#save-project-btn").prop('disabled', true);
		let url = $('meta[name=app-url]').attr("content") + "/projects/" + $("#update_id").val();
  		let data = {
  			id: $("#update_id").val(),
      		name: $("#name").val(),
      		description: $("#description").val(),
    	};
		$.ajax({
			headers: {
                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
	        },
	        url: url,
	        type: "PUT",
	        data: data,
	        success: function(response) {
	        	$("#save-project-btn").prop('disabled', false);
	        	let successHtml = '<div class="alert alert-success" role="alert"><b>Project Updated Successfully</b></div>';
	        	$("#alert-div").html(successHtml);
	        	$("#name").val("");
	        	$("#description").val("");
	        	showAllProjects();
	        	$("#form-modal").modal('hide');
	        },
	        error: function(response) {
	        	/*
					show validation error
	        	*/
	        	$("#save-project-btn").prop('disabled', false);
	          	if (typeof response.responseJSON.errors !== 'undefined') 
	          	{
	          		console.log(response)
				    let errors = response.responseJSON.errors;
				    let descriptionValidation = "";
				    if (typeof errors.description !== 'undefined') 
	          		{
	          			descriptionValidation = '<li>' + errors.description[0] + '</li>';
	          		}
	          		let nameValidation = "";
				   	if (typeof errors.name !== 'undefined') 
	          		{
	          			nameValidation = '<li>' + errors.name[0] + '</li>';
	          		}
				    
				    let errorHtml = '<div class="alert alert-danger" role="alert">' +
				    					'<b>Validation Error!</b>' +
				  						'<ul>' + nameValidation + descriptionValidation + '</ul>' +
									'</div>';
					$("#error-div").html(errorHtml);		
				}
	        }
      	});
	}

	/*
		get and display the record info on modal
	*/
	function showProject(id)
	{
		$("#name-info").html("");
		$("#description-info").html("");
		let url = $('meta[name=app-url]').attr("content") + "/projects/" + id +"";
		$.ajax({
	        url: url,
	        type: "GET",
	        success: function(response) {
	           	let project = response.project;
	          	$("#name-info").html(project.name);
				$("#description-info").html(project.description);
				$("#view-modal").modal('show');	
				
	        },
	        error: function(response) {
	          	console.log(response.responseJSON)
	        }
      	});
	}

	/*
		delete record function
	*/
	function destroyProject(id)
	{
		let url = $('meta[name=app-url]').attr("content") + "/projects/" + id;
  		let data = {
      		name: $("#name").val(),
      		description: $("#description").val(),
    	};
		$.ajax({
			headers: {
                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
	        },
	        url: url,
	        type: "DELETE",
	        data: data,
	        success: function(response) {
	        	let successHtml = '<div class="alert alert-success" role="alert"><b>Project Deleted Successfully</b></div>';
	        	$("#alert-div").html(successHtml);
	            showAllProjects();
	        },
	        error: function(response) {
	          	console.log(response.responseJSON)
	        }
      	});
	}

</script>
</body>
</html>

Step 7 : Run the Application

After finishing the steps above, you can now run your application by executing the code below:

php artisan serve

After successfully running your app, open this URL in your browser:

http://localhost:8000

Screenshots:

Laravel 7 AJAX CRUD (App project index page):

laravel-ajax-crud-index-page-image

Laravel 7 AJAX CRUD App (create project form modal):

laravel-ajax-crud-create-modal-image

Laravel 7 AJAX CRUD App (edit project form modal):

laravel-ajax-crud-edit-modal-image

Laravel 7 AJAX CRUD App (show project information modal):

laravel-ajax-crud-show-modal-image