Laravel 12- Edit Recode User Information

Laravel 12- Edit Recode User Information

1. Blade Template - Frontend: Offcanvas for Editing User Information

This part of the code defines the HTML structure for the offcanvas modal that appears when editing user information.

Offcanvas Section (Editing Form)

<!-- Offcanvas for Editing User Information --> <div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvasRight" aria-labelledby="offcanvasRightLabel"> <!-- Header Section of the Offcanvas --> <div class="offcanvas-header"> <h5 class="offcanvas-title" id="offcanvasRightLabel">Edit User Information</h5> <button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button> </div> <!-- Body Section of the Offcanvas (Form for Editing User Information) --> <div class="offcanvas-body"> <form id="editUserForm" action="{{ route('update-user') }}" method="POST" enctype="multipart/form-data"> @csrf <!-- Profile Image Section --> <div class="mb-3 text-center"> <input type="file" id="e_image_upload" name="profile_image" accept="image/*" class="d-none"> <input type="hidden" id="e_hidden_image" name="hidden_image"> <div class="d-flex justify-content-center"> <span class="input-group-text p-2 rounded-4" id="e_image_upload_trigger" style="cursor: pointer;"> <img id="e_image-circle-preview" src="" alt="User Image" class="rounded-circle d-none" width="60" height="60"> <h4 class="fw-bold mb-0" id="e_image-circle"></h4> </span> </div> </div> <!-- User Information Fields --> <div class="mb-3"> <label for="userID" class="form-label">User ID</label> <input type="text" class="form-control" id="e_user_id" name="user_id" readonly> </div> <div class="mb-3"> <label for="userName" class="form-label">Full Name</label> <input type="text" class="form-control" id="e_name" name="name" placeholder="Enter full name" required> </div> <div class="mb-3"> <label for="userEmail" class="form-label">Email Address</label> <input type="email" class="form-control" id="e_email" name="email" placeholder="Enter email" required> </div> <div class="mb-3"> <label for="userPhone" class="form-label">Phone Number</label> <input type="tel" class="form-control" id="e_phone_number" name="phone_number" placeholder="Enter phone number"> </div> <div class="mb-3"> <label for="position" class="form-label">Position</label> <input type="text" class="form-control" id="e_position" name="position" placeholder="Enter position"> </div> <div class="mb-3"> <label for="department" class="form-label">Department</label> <input type="text" class="form-control" id="e_department" name="department" placeholder="Enter department"> </div> <!-- User Role Selection --> <div class="mb-3"> <label for="userRole" class="form-label">User Role</label> <select class="form-select" id="e_role_name" name="role_name"> <option value="Admin">Admin</option> <option value="Editor">Editor</option> <option value="User">User</option> </select> </div> <!-- User Status Selection --> <div class="mb-3"> <label for="userStatus" class="form-label">Status</label> <select class="form-select" id="e_status" name="status"> <option value="Active">Active</option> <option value="Inactive">Inactive</option> <option value="Pending">Pending</option> <option value="Suspended">Suspended</option> </select> </div> </form> </div> <!-- Footer Section with Buttons --> <div class="offcanvas-footer"> <button type="button" class="btn btn-outline-secondary" data-bs-dismiss="offcanvas">Cancel</button> <button type="submit" class="btn btn-primary" form="editUserForm">Save Changes</button> </div> </div>

Explanation of Key Sections:

  • File Upload for Profile Image:

    • Hidden file input allows users to upload their profile image, and it shows a preview in the offcanvas. The e_image-circle-preview image element will display the selected image.

  • Form Fields for User Information:

    • Fields for User ID, Name, Email, Phone, Position, Department, Role, and Status allow updating these details for the user.

  • Save and Cancel Buttons:

    • The form can be submitted via the "Save Changes" button, or canceled using the "Cancel" button.

2. JavaScript - Handling Form and DataTable

DataTable Initialization:

$(document).ready(function() { const table = $('#userListing').DataTable({ lengthMenu: [ [10, 25, 50, 100, 150], [10, 25, 50, 100, 150] ], buttons: ['pageLength'], pageLength: 10, order: [[5, 'desc']], scrollX: true, processing: true, serverSide: true, ajax: { url: "{{ route('get-data-user.listing') }}", }, columns: [ { data: 'action', orderable: false, searchable: false }, { data: 'id' }, { data: 'name' }, { data: 'user_id' }, { data: 'email' }, { data: 'position' }, { data: 'phone_number' }, { data: 'join_date' }, { data: 'last_login' }, { data: 'role_name' }, { data: 'department' }, { data: 'status' }, ], columnDefs: [ { targets: 0, className: 'th-active-fixed' } ] }); });
  • DataTable Setup:

    • Initializes a DataTable with pagination, sorting, and server-side processing, pulling data from the backend via the route get-data-user.listing.

    • Columns are defined to display user details like id, name, email, position, etc.

Populating Edit Form with Data:

$(document).on('click', '.userUpdate', function() { const _this = $(this).closest('tr'); // Populate form fields with current user data $('#e_user_id').val(_this.find('.user_id').text()); $('#e_name').val(_this.find('.name').text()); $('#e_email').val(_this.find('.email').text()); $('#e_role_name').val(_this.find('.role_name').text()).change(); $('#e_position').val(_this.find('.position').text()).change(); $('#e_phone_number').val(_this.find('.phone_number').text()); $('#e_department').val(_this.find('.department').text()); $('#e_status').val(_this.find('.status').text()).change(); $('#e_image-circle').text(_this.find('.image-circle').text()); const imgName = _this.find('.image-circle').data('image-circle'); if (imgName) { $('#e_image-circle-preview').attr('src', '/assets/images/' + imgName).removeClass('d-none'); $('#e_image-circle').addClass('d-none'); } else { $('#e_image-circle').removeClass('d-none'); $('#e_image-circle-preview').addClass('d-none'); } $('#e_hidden_image').val(imgName); });
  • Click Event for User Update:

    • When the "Edit" button is clicked on a user row, the data for that user is populated into the form fields in the offcanvas modal.

    • The profile image preview is also set based on the current data (imgName).

Handling Image Upload:

$(function () { $('#e_image_upload_trigger').click(() => $('#e_image_upload').click()); $('#e_image_upload').change(function () { const file = this.files[0]; if (file && file.type.startsWith('image/')) { const reader = new FileReader(); reader.onload = e => $('#e_image-circle-preview').attr('src', e.target.result).removeClass('d-none'); reader.readAsDataURL(file); $('#e_image-circle').addClass('d-none'); } else { alert('Please upload a valid image file.'); } }); });
  • Image Preview:

    • When a new image is selected for upload, it is displayed in the #e_image-circle-preview element.

    • The image preview replaces the placeholder text (#e_image-circle).

3. Laravel Controller - Backend

getData Method:

public function getData(Request $request) { // region: Initialize DataTables Parameters $draw = $request->get('draw'); $start = $request->get('start'); $rowPerPage = $request->get('length'); $order = $request->get('order'); $columns = $request->get('columns'); $search = $request->get('search'); // endregion // region: Set Default Sorting if (isset($order[0]['column']) && isset($columns[$order[0]['column']]['data'])) { $columnIndex = $order[0]['column']; $columnName = $columns[$columnIndex]['data']; $columnSortOrder = $order[0]['dir'] ?? 'asc'; } else { $columnName = 'id'; // default column $columnSortOrder = 'asc'; } // endregion // region: Define Search Value and Searchable Columns $searchValue = $search['value'] ?? ''; $searchColumns = [ 'name', 'user_id', 'email', 'position', 'phone_number', 'join_date', 'role_name', 'status', 'department' ]; // endregion // region: Base Query & Total Count $users = DB::table('users'); $totalRecords = $users->count(); // endregion // region: Total Filtered Count $totalRecordsWithFilter = $users->where(function ($query) use ($searchValue, $searchColumns) { foreach ($searchColumns as $column) { $query->orWhere($column, 'like', "%{$searchValue}%"); } })->count(); // endregion // region: Fetch Filtered Data $records = DB::table('users') ->where(function ($query) use ($searchValue, $searchColumns) { foreach ($searchColumns as $column) { $query->orWhere($column, 'like', "%{$searchValue}%"); } }) ->orderBy($columnName, $columnSortOrder) ->skip($start) ->take($rowPerPage) ->get(); // endregion // region: Status Badge Classes $badgeClasses = [ 'Active' => 'bg-success-subtle text-success', 'Inactive' => 'bg-danger-subtle text-danger', 'Pending' => 'bg-primary-subtle text-primary', 'Suspended' => 'bg-warning-subtle text-warning', ]; // endregion // region: Format Data for DataTable $data_arr = []; foreach ($records as $key => $record) { $last_login = Carbon::parse($record->last_login)->diffForHumans(); // Action Buttons $action = ' <div class="d-flex gap-2"> <button class="btn btn-info btn-sm" data-id="'.$record->id.'" data-bs-toggle="offcanvas" data-bs-target="#viewUser" aria-controls="viewUser"> <i class="bi bi-eye"></i> </button> <button class="btn btn-warning btn-sm userUpdate" data-id="'.$record->id.'" data-bs-toggle="offcanvas" data-bs-target="#offcanvasRight"> <i class="bi bi-pencil"></i> </button> <button class="btn btn-danger btn-sm" data-bs-toggle="modal" data-bs-target="#modalDeleteUser"> <i class="bi bi-trash"></i> </button> </div>'; // Avatar or Initials $fullName = $record->name; $parts = explode(' ', $fullName); $initials = ''; foreach ($parts as $part) { $initials .= strtoupper(substr($part, 0, 1)); } if (!empty($record->avatar)) { $nameAvatar = '<div class="d-flex align-items-center rounded"> <img src="'.url('/assets/images/'.$record->avatar).'" alt="Profile" data-image-circle="'.$record->avatar.'" class="rounded-circle me-2 image-circle"> <span class="fw-medium name">'.$record->name.'</span> </div>'; } else { $nameAvatar = '<div class="d-flex"> <span class="d-flex align-items-center justify-content-center bg-secondary text-white rounded-circle fw-bold small image-circle me-2"> '.$initials.' </span> <span class="fw-medium name">'.$record->name.'</span> </div>'; } // Badge Styling $statusText = $record->status; $badgeClass = $badgeClasses[$statusText] ?? 'bg-secondary-subtle text-secondary'; $status = "<span class=\"badge {$badgeClass} status\">{$statusText}</span>"; $data_arr[] = [ "action" => $action, "id" => '<span class="id" data-id="'.$record->id.'">'.($start + $key + 1).'</span>', "name" => '<span>'.$nameAvatar.'</span>', "user_id" => '<span class="user_id">'.$record->user_id.'</span>', "email" => '<span class="email">'.$record->email.'</span>', "position" => '<span class="position">'.$record->position.'</span>', "phone_number" => '<span class="phone_number">'.$record->phone_number.'</span>', "join_date" => $record->join_date, "last_login" => $last_login, "role_name" => '<span class="role_name">'.$record->role_name.'</span>', "department" => '<span class="department">'.$record->department.'</span>', "status" => $status, ]; } // endregion // region: Return JSON Response $response = [ "draw" => intval($draw), "iTotalRecords" => $totalRecords, "iTotalDisplayRecords" => $totalRecordsWithFilter, "aaData" => $data_arr ]; return response()->json($response); // endregion }
  • Data Fetching:

    • Handles the data fetching, pagination, and filtering based on search criteria sent from the frontend (via DataTables).

    • It retrieves all records matching the search query.

updateRecord Method:

public function updateRecord(Request $request) { // Begin a database transaction to ensure atomicity DB::beginTransaction(); try { // Retrieve data from the request $user_id = $request->user_id; $name = $request->name; $email = $request->email; $role_name = $request->role_name; $position = $request->position; $phone_number = $request->phone_number; $department = $request->department; $status = $request->status; $image_name = $request->hidden_image; // Current image name from hidden input // Prepare the current date for logging (optional, can be added to the update) $todayDate = Carbon::now()->toDayDateTimeString(); // Check if a new profile image is uploaded $image = $request->file('profile_image'); if ($image) { // Delete the old image if it exists if ($image_name && file_exists(public_path('assets/images/'.$image_name))) { unlink(public_path('assets/images/'.$image_name)); } // Generate a new image name and move the file to the public directory $image_name = time() . '.' . $image->getClientOriginalExtension(); $image->move(public_path('assets/images'), $image_name); } // Prepare the data to update in the database $update = [ 'name' => $name, 'email' => $email, 'role_name' => $role_name, 'position' => $position, 'phone_number' => $phone_number, 'department' => $department, 'status' => $status, 'avatar' => $image_name, // Save the new or existing image name ]; // Perform the update User::where('user_id', $user_id)->update($update); // Commit the transaction DB::commit(); // Redirect back with a success message return redirect()->back()->with('success', 'User updated successfully :)'); } catch (\Exception $e) { // If an error occurs, rollback the transaction DB::rollback(); // Log the error for debugging purposes \Log::error('User update failed', ['error' => $e->getMessage()]); // Return a failure message return redirect()->back()->with('error', 'User update failed. Please try again.'); } }
  • Update User Data:

    • This method updates the user details in the database, handling the image upload logic as well.

    • A transaction is used to ensure that all changes are committed successfully, and an error handling mechanism is in place in case anything fails.

This detailed step-by-step breakdown should make it easier to understand how the frontend (Blade), JavaScript, and backend (Laravel) work together to allow users to view, edit, and update their information with validation, image handling, and real-time feedback.

Souy Soeng

Souy Soeng

Our website teaches and reads PHP, Framework Laravel, and how to download Admin template sample source code free. Thank you for being so supportive!

Github

Post a Comment

CAN FEEDBACK
close