1

So I have a page to display courses a student is enrolled in and also in that page is a form in a modal all which is built as a Laravel web project, and the purpose of that form is that a user selects courses(all data is pulled from a database) that they want to enroll in and click 'enroll' to add it to courses they are enrolled in. So the form was built with some elements of jQuery ajax and now when there is a successful enrollment it runs and displays a message on the modal, the problem now is with a successful enrollment I still have to refresh the page before I see the course listed, I'm looking for a way to fix it so that I don't have to refresh the page after exiting the modal

this is my form in my course.blade.php

 <div id="enroll-form">
                    <div class="modal-body">
                       
                        <form method="post" action="{{ route('enroll') }}">
                            @csrf
                    
                            <label for="courses">Select Courses:</label>
                            <select class="form-select"name="courses[]"  id="courses"   aria-label="Default select example">
                                <option selected>Select Course</option>
                                @foreach ($availableCourses as $course)
                                    <option value="{{ $course->courseId }}">{{ $course->courseTitle }}</option>
                                @endforeach
                            </select>
                    </div>
                    <div class="modal-footer">
                        <button class="btn btn-secondary text-black" type="button" data-dismiss="modal">Cancel</button>
                        <button class="btn btn-primary text-black" type="submit">Enroll</button>
                        
                    </div>
                </form>
                    
                    <div class="card-footer">
                        <div id="enroll-messages"></div>
                    </div>
                </div>

This is my script code

<script src="{{asset('vendor/jquery/jquery.min.js')}}"></script>
 <script>
        $(document).ready(function() {
            $('#enroll-form form').submit(function(e) {
                e.preventDefault();
    
                $.ajax({
                    type: 'POST',
                    url: $(this).attr('action'),
                    data: $(this).serialize(),
                    success: function(response) {
                        $('#enroll-messages').html('<div class="alert alert-success">' + response.success + '</div>');
                    },
                    error: function(response) {
                        $('#enroll-messages').html('<div class="alert alert-danger">' + response.responseJSON.error + '</div>');
                    }
                });
            });
        });
    </script>

This is my courseController

 public function index()
    {
        $studentId = Auth::user()->studentId; //Retrieve the currently logged-in student's ID using the Auth facade.
        $availableCourses = Course::all();
     
        $user = User::with('courses')->find($studentId);
       
        return view('course', 
    [
        
        'user' => $user,
        'availableCourses' => $availableCourses
    ]);
    }

    public function enroll(Request $request)
    {
        $studentId = Auth::user()->studentId;
        $coursesToEnroll = $request->input('courses', []);
        $user = User::with('courses')->find($studentId);
        $alreadyEnrolled = $user->courses->pluck('courseId')->intersect($coursesToEnroll);
        
        if ($alreadyEnrolled->count() > 0) {
            $courseTitles = Course::whereIn('courseId', $alreadyEnrolled)->pluck('courseTitle')->implode(', ');
            return response()->json(['error' => "You are already enrolled in the following course(s): $courseTitles."], 422);
        }
    
        $user->courses()->syncWithoutDetaching($coursesToEnroll);
    
        return response()->json(['success' => 'Enrollment successful.']);
    }
    
    

With the coursecontroller this is how I loop through the database with this code block in my couse.blade.php to display the courses(PS: Its a jquery datatable)

 <table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
                                  
                                    <thead>
                                        <tr>
                                            <th>Name <i> fa fa-angle-up</i></th>
                                            <th>Course Code</th>
                                            <th>Schedule</th>
                                            <th>Progress</th>
                                        </tr>
                                    </thead>
                                  
                                   
                                    <tbody>
                                        @foreach ($user->courses as $item)
                                        <tr>
                                            <td>{{$item->courseTitle}}</td>
                                            <td>{{$item->courseCode}}</td>
                                            <td>{{$item->courseSchedule}}</td>
                                            <td>{{$item->courseProg}}%</td>
                                            
                                        </tr>
                                        @endforeach
                                        
                                    </tbody>
                                  
                                </table>

And finally my route

Route::get('/course', [CourseController::class, 'index'])
    ->middleware(['auth', 'verified'])
    ->name('course');

Route::post('/enroll', [CourseController::class, 'enroll'])
    ->middleware(['auth', 'verified'])
    ->name('enroll');

With this current code, whenever I try selecting a new course it runs successfully, the success message shows as it should but I still have to reload the page to see it displayed in the section allocated for it. (PS: Also when a user enrolls in a course already registered in the error message also runs as it should saying cant add course cause already registered'

Zion
  • 21
  • 2

2 Answers2

0

Please reload the current page after the successful action code below.

<script src="{{asset('vendor/jquery/jquery.min.js')}}"></script>
<script>
            $(document).ready(function() {
                $('#enroll-form form').submit(function(e) {
                    e.preventDefault();
        
                    $.ajax({
                        type: 'POST',
                        url: $(this).attr('action'),
                        data: $(this).serialize(),
                        success: function(response) {
                            $('#enroll-messages').html('<div class="alert alert-success">' + response.success + '</div>');
    //for refresh your page
    location.reload();
                        },
                        error: function(response) {
                            $('#enroll-messages').html('<div class="alert alert-danger">' + response.responseJSON.error + '</div>');
                        }
                    });
                });
            });
 </script>
Aditya
  • 107
  • 6
  • Okay, this works... but is it possible for the page not to refresh, just being curious, like when the course is added from the modal the user can close it and just see the new course added – Zion Aug 23 '23 at 10:43
0

you can achieve that, you can add load new course content to the table after submitting the form, add a new (route, view, controller method):

web.php

Add a route for loading courses dynamically:

Route::get('/course-api', [CourseController::class, 'loadOnlyCourses'])
->middleware(['auth', 'verified'])
->name('course-api');

courseController.php:

...

public function loadOnlyCourses()
{
    //same code as index()
        $studentId = Auth::user()->studentId;
        $availableCourses = Course::all();
     
        $user = User::with('courses')->find($studentId);
   
    return view('course-only', 
    [
        'availableCourses' => $availableCourses
    ]);
}

...

resources/views/course-only.blade.php

add this view to load the courses html only without the full page :

@foreach ($user->courses as $item)
    <tr>
        <td>{{$item->courseTitle}}</td>
        <td>{{$item->courseCode}}</td>
        <td>{{$item->courseSchedule}}</td>
        <td>{{$item->courseProg}}%</td>
        
    </tr>
@endforeach

js script

now add the fetch code to your script :

<script>
    $(document).ready(function() {
        $('#enroll-form form').submit(function(e) {
            e.preventDefault();

            $.ajax({
                type: 'POST',
                url: $(this).attr('action'),
                data: $(this).serialize(),
                success: function(response) {
                    $('#enroll-messages').html('<div class="alert alert-success">' + response.success + '</div>');
                    refreshTable();
                },
                error: function(response) {
                    $('#enroll-messages').html('<div class="alert alert-danger">' + response.responseJSON.error + '</div>');
                }
            });
        });
    });

    function refreshTable() {
        $("#dataTable tbody").load("{{route('course-api')}}");
    }
</script>
HichemTech
  • 389
  • 2
  • 6
  • you can use [Livewire](https://laravel-livewire.com) specially [Livewire](https://laravel-livewire.com/docs/2.x/polling) polling, this helps you make data alive in your webpage without needs to refresh the page everytime, or making your own scripts to handle theauto refresh. – HichemTech Aug 23 '23 at 13:25
  • hey okay thanks, and back to the former question the code you showed worked to an extent on the datatable, so now a new course added shows on it, but its only temporary because when i select show all entries that new course doesn't show on it and the paging isn't also updated, – Zion Aug 23 '23 at 13:25
  • which pagination ? and where is "show all entries", i guess you didn't mentionned it in the code, but you can update the intire table with its pagination inside `*resources/views/course-only.blade.php*`, and update `$("#dataTable tbody").load("{{route('course-api')}}");` to something like `$("#tableParent").load("{{route('course-api')}}");`, also like i said in previous comment i recommand you to start using [Livewire](https://laravel-livewire.com) because it's made for this kind of things. I hoop this helped you. – HichemTech Aug 23 '23 at 13:34