Laravel 11 Ajax CRUD Image Upload Tutorial

To create laravel 11 Ajax crud with an image upload app, You need to create a controller and method to perform crud operation from the database table, and create forms to send data to the server using jQuery ajax, and then define routes to handle crud operation requests in laravel 11 applications.

In this example guide, we will create a task Ajax CRUD application in Laravel 11 with image upload functionality for managing tasks between the app and the database, this application will allow users to create, read, update, and delete tasks on the database table without reloading the web page.

To develop ajax crud with image upload operation application in laravel 11

Here are steps:

Step 1 – Download New Laravel 11 Application

Open cmd or terminal window and run the following command to download and install new laravel 11 setup into your server:

composer create-project --prefer-dist laravel/laravel blog

Step 2 – Initialize Database with Application

Open and edit .env file from laravel application root folder, to configure the database in it; something like this:

 DB_CONNECTION=mysql
 DB_HOST=127.0.0.1
 DB_PORT=3306
 DB_DATABASE=db_nmae
 DB_USERNAME=db_user_name
 DB_PASSWORD=db_user_password

Step 3 – Create Migration And Model

Open cmd or terminal window and navigate to laravel 11 project folder by cd project-name command, and then create model and migration file using php artisan make:model Task -m command:

cd blog
php artisan make:model Task -m

Add the fields name in create_tasks_table.php file, which is database/migrations/ folder; something like this:

    public function up(): void
    {
        Schema::create('tasks', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->string('task_code')->nullable();
            $table->string('image')->nullable();
            $table->text('description');
            $table->timestamps();
        });
    }

Run migration with the help of php artisan migrate command to create tables in select database:

php artisan migrate

Step 4 – Install Yajra DataTables Package

Run the following command on cmd or terminal window to install latest yajra dataTables package, which is help to show records on HTML table without page refresh:

composer require yajra/laravel-datatables-oracle

Step 5 – Add Routes

Open web.php file from routes folder, and add ajax crud image upload routes in it; something like this:

use App\Http\Controllers\TaskController;

Route::get('tasks', [TaskController::class, 'index']);
Route::get('taskEdit/{id}/', [TaskController::class, 'edit']);
Route::post('taskStore', [TaskController::class, 'store']);
Route::get('taskDelete/{id}', [TaskController::class, 'destroy']);

Step 6 – Create Controller and Methods

Run php artisan make:controller TaskController command to create controller file, which is help to perform crud operations from database:

php artisan make:controller TaskController

Create some methods in TaskController.php, which are used to perform crud operations from database; something like this:

<?php

namespace App\Http\Controllers;

use App\Models\Task;
use Illuminate\Http\Request;
use Response;
use DataTables;

class TaskController extends Controller
{
    public function index()
    {
        if(request()->ajax()) {
            return datatables()->of(Task::select('*'))
            ->addColumn('action', 'task-action')
            ->addColumn('image', 'image')
            ->rawColumns(['action','image'])
            ->addIndexColumn()
            ->make(true);
        }
        return view('tasks');
    }
    public function store(Request $request)
    {
        request()->validate([
            'image' => 'image|mimes:jpeg,png,jpg,gif,svg|max:2048',
       ]);
        $taskId = $request->task_id;

        if ($files = $request->file('image')) {

           //delete old file
           \File::delete('public/task/'.$request->hidden_image);

           //insert new file
           $destinationPath = 'public/task/'; // upload path
           $profileImage = date('YmdHis') . "." . $files->getClientOriginalExtension();
           $files->move($destinationPath, $profileImage);
           $image = "$profileImage";
        }

        $task = Task::find($taskId) ?? new Task();

        // Set the individual attributes
        $task->id = $taskId;
        $task->title = $request->title;
        $task->task_code = $request->task_code;
        $task->description = $request->description;
        $task->image = $image;

        // Save the task
        $task->save();

        return Response::json($task);
    }
    public function edit($id)
    {
        $where = array('id' => $id);
        $task  = Task::where($where)->first();

        return Response::json($task);
    }
    public function destroy($id)
    {
        $data = Task::where('id',$id)->first(['image']);
        \File::delete('public/task/'.$data->image);
        $task = Task::where('id',$id)->delete();

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

Step 7 – Create Blade View

Create two blade views file, which are used to display create, edit, delete button and task list on web page.

Go to resources/views folder and create task-action.blade.php file, and create delete and edit button in it something like this:

<a href="javascript:void(0)" data-toggle="tooltip"  data-id="{{ $id }}" data-original-title="Edit" class="edit btn btn-success edit-task">
    Edit
</a>
<a href="javascript:void(0);" id="delete-task" data-toggle="tooltip" data-original-title="Delete" data-id="{{ $id }}" class="delete btn btn-danger">
    Delete
</a>

And create tasks.blade.php file in resources/views/ folder and create HTML table into it to show list of tasks records with add, edit, and delete button and also add jQuery ajax code in it; something like this:

<!DOCTYPE html>

<html lang="en">
<head>
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>Laravel 11 Ajax CRUD Image Upload Tutorial - Tutsmake.com</title>

<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
<script src="https://code.jquery.com/jquery-3.6.1.min.js"></script>
<link  href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.min.css" rel="stylesheet">
<script src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.min.js"></script>

</head>
<body>
<div class="container" style="margin-top: 1%;">
  <h1>Laravel Ajax CRUD Image Upload Tutorial - Tutsmake.com</h1>
  <a href="javascript:void(0)" class="btn btn-info ml-3" id="create-new-task">Add New</a>
  <br><br>

  <table class="table table-bordered table-striped" id="laravel_datatable">
    <thead>
      <tr>
        <th>ID</th>
        <th>S. No</th>
        <th>Image</th>
        <th>Title</th>
        <th>Task Code</th>
        <th>Description</th>
        <th>Created at</th>
        <th>Action</th>
      </tr>
    </thead>
  </table>
</div>
<div class="modal fade" id="ajax-task-modal" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h4 class="modal-title" id="taskCrudModal"></h4>
      </div>
      <div class="modal-body">
        <form id="taskForm" name="taskForm" class="form-horizontal" enctype="multipart/form-data">
          <input type="hidden" name="task_id" id="task_id">
          <div class="form-group">
            <label for="name" class="col-sm-2 control-label">Title</label>
            <div class="col-sm-12">
              <input type="text" class="form-control" id="title" name="title" placeholder="Enter Tilte" value="" maxlength="50" required="">
            </div>
          </div>
          <div class="form-group">
            <label for="name" class="col-sm-2 control-label">Task Code</label>
            <div class="col-sm-12">
              <input type="text" class="form-control" id="task_code" name="task_code" placeholder="Enter Tilte" value="" maxlength="50" required="">
            </div>
          </div>

          <div class="form-group">
            <label class="col-sm-2 control-label">Description</label>
            <div class="col-sm-12">
              <input type="text" class="form-control" id="description" name="description" placeholder="Enter Description" value="" required="">
            </div>
          </div>

          <div class="form-group">
            <label class="col-sm-2 control-label">Image</label>
            <div class="col-sm-12">
              <input id="image" type="file" name="image" accept="image/*" onchange="readURL(this);">
              <input type="hidden" name="hidden_image" id="hidden_image">
            </div>
          </div>
          <img id="modal-preview" src="https://via.placeholder.com/150" alt="Preview" class="form-group hidden" width="100" height="100">
          <div class="col-sm-offset-2 col-sm-10">
            <button type="submit" class="btn btn-primary" id="btn-save" value="create">Save changes
            </button>
          </div>
        </form>
      </div>
      <div class="modal-footer">

      </div>
    </div>
  </div>
</div>
<script>

 var SITEURL = '{{URL::to('')}}'+'/';
 console.log(SITEURL);
 $(document).ready( function () {
   $.ajaxSetup({
      headers: {
          'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
      }
  });

  $('#laravel_datatable').DataTable({
         processing: true,
         serverSide: true,
         ajax: {
          url: SITEURL + "tasks",
          type: 'GET',
         },
         columns: [
                  {data: 'id', name: 'id', 'visible': false},
                  {data: 'DT_RowIndex', name: 'DT_RowIndex', orderable: false,searchable: false},
                  {data: 'image', name: 'image', orderable: false},
                  { data: 'title', name: 'title' },
                  { data: 'task_code', name: 'task_code' },
                  { data: 'description', name: 'description' },
                  { data: 'created_at', name: 'created_at' },
                  {data: 'action', name: 'action', orderable: false},
               ],
        order: [[0, 'desc']]
      });
    /*  When user click add user button */
    $('#create-new-task').click(function () {
        $('#btn-save').val("create-task");
        $('#task_id').val('');
        $('#taskForm').trigger("reset");
        $('#taskCrudModal').html("Add New task");
        $('#ajax-task-modal').modal('show');
        $('#modal-preview').attr('src', 'https://via.placeholder.com/150');
    });

   /* When click edit user */
    $('body').on('click', '.edit-task', function () {
      var task_id = $(this).data('id');
      $.get('taskEdit/' + task_id, function (data) {
         $('#title-error').hide();
         $('#task_code-error').hide();
         $('#description-error').hide();
         $('#taskCrudModal').html("Edit Task");
          $('#btn-save').val("edit-task");
          $('#ajax-task-modal').modal('show');
          $('#task_id').val(data.id);
          $('#title').val(data.title);
          $('#task_code').val(data.task_code);
          $('#description').val(data.description);
          $('#modal-preview').attr('alt', 'No image available');
          if(data.image){
            $('#modal-preview').attr('src', SITEURL +'public/task/'+data.image);
            $('#hidden_image').attr('src', SITEURL +'public/task/'+data.image);
          }

      })
   });
    $('body').on('click', '#delete-task', function () {

        var task_id = $(this).data("id");

        if(confirm("Are You sure want to delete !")){
          $.ajax({
              type: "get",
              url: SITEURL + "taskDelete/"+task_id,
              success: function (data) {
              var oTable = $('#laravel_datatable').dataTable();
              oTable.fnDraw(false);
              },
              error: function (data) {
                  console.log('Error:', data);
              }
          });
        }
    });
   });

  $('body').on('submit', '#taskForm', function (e) {
      e.preventDefault();
      var actionType = $('#btn-save').val();
      $('#btn-save').html('Sending..');
      var formData = new FormData(this);
      $.ajax({
          type:'POST',
          url: SITEURL + "taskStore",
          data: formData,
          cache:false,
          contentType: false,
          processData: false,
          success: (data) => {

              $('#taskForm').trigger("reset");
              $('#ajax-task-modal').modal('hide');
              $('#btn-save').html('Save Changes');
              var oTable = $('#laravel_datatable').dataTable();
              oTable.fnDraw(false);
          },
          error: function(data){
              console.log('Error:', data);
              $('#btn-save').html('Save Changes');
          }
      });
  });
function readURL(input, id) {
  id = id || '#modal-preview';
  if (input.files && input.files[0]) {
      var reader = new FileReader();
      reader.onload = function (e) {
          $(id).attr('src', e.target.result);
      };
      reader.readAsDataURL(input.files[0]);
      $('#modal-preview').removeClass('hidden');
      $('#start').hide();
  }
}
</script>
</body>
</html>

Now, create image.blade.php file in resources/views folder to show image in tasks list; something like this:

@if($image)
 <img id="preview" src="{{ ('public/task/'.$image) }}" alt="Preview" class="form-group hidden" width="100" height="100">
@else
 <img id="preview" src="https://via.placeholder.com/150" alt="Preview" class="form-group hidden" width="100" height="100">
@endif

Step 8 – Run and Test Application

Run php artisan serve command to start application server:

php artisan storage:link
php artisan serve

Open browser with http://127.0.0.1:8000/tasks:

http://127.0.0.1:8000/tasks

Conclusion

We hope you have learned how to create AJAX CRUD operation application with image upload feature using jQuery AJAX dataTables js in laravel 11 apps.

Recommended Guides

If you have any questions or thoughts to share, use the comment form below to reach us.

AuthorDevendra Dode

Greetings, I'm Devendra Dode, a full-stack developer, entrepreneur, and the proud owner of Tutsmake.com. My passion lies in crafting informative tutorials and offering valuable tips to assist fellow developers on their coding journey. Within my content, I cover a spectrum of technologies, including PHP, Python, JavaScript, jQuery, Laravel, Livewire, CodeIgniter, Node.js, Express.js, Vue.js, Angular.js, React.js, MySQL, MongoDB, REST APIs, Windows, XAMPP, Linux, Ubuntu, Amazon AWS, Composer, SEO, WordPress, SSL, and Bootstrap. Whether you're starting out or looking for advanced examples, I provide step-by-step guides and practical demonstrations to make your learning experience seamless. Let's explore the diverse realms of coding together.

Leave a Reply

Your email address will not be published. Required fields are marked *