Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Yugi's avatar
Level 23

Performing an ajax request using vuejs, pretty simple process, pretty hard to implement.

I need some help in implementing a basic ajax request through vue to my laravel back-end, I have a boolean named completed on a table called courses, and I have a view that fetches all courses assigned to a specific user and allows them to press a button to change the current status of the course, either completed or not, that's it, that's all I wanna do, right now I can do it normally through get and post requests, obviously results in a refresh of the page, I want that to be dynamic with just refreshing the dom, I am so frustrated that I couldn't figure this out on my own because I think It should be easy, turns out I know nothing when it comes to using vuejs, help would be appreciated.

Here is the significant part of my CoursesController:

  public function toggling($name)
  {
    $course = Course::where(['name' => $name])->first();

    $course->completed = !$course->completed;
    $course->save();

    // return redirect()->back();
    return response()->json(['course' => $course], 202);
    }

And here is the significant part of the view that provides the courses to the user, it's a part of a table:

<td>
                   <form method="POST" action="{{ route('course.completed', $course->name) }}" id="form-submit">
                       {{ csrf_field() }}

                           @if ($course->completed == true)
                             <button type="submit" class="btn btn-sm" id="coursetogglingtrue">Done!</button>
                           @else
                               <button type="submit" class="btn btn-sm" id="coursetogglingfalse">Not Yet!</button>
                           @endif

                   </form>
</td>

I think I should prevent the default action of the form, and I remember that vuejs had a .prevent or something similar but I just can't remember/find it, I think this whole form should be re-written to apply the new logic where it depends on vuejs.

routes/web.php, right now I just commented out that route and copied it over to api.php:

Route::get('/MyCourses', 'CoursesController@myCourses')->name('student.mycourses');
// Route::post('/MyCourses/{name}', 'CoursesController@toggling')->name('course.completed'); //Changing The Completed Status On The Courses Table

routes/api.php:

Route::post('/MyCourses/{name}', 'CoursesController@toggling')->name('course.completed');

For that response()->json() thing, I actually got that from a video doing mostly the same thing, but then I didn't know what to do with it, when the route is triggered I get redirect to api/Mycourses/{name} and the course object would be displayed in json, I'm not really sure what I should do at this point, but what I want to do is when the user clicks on that button the other id gets applied, and then an ajax request would be sent so that the value of the completed column for that course would be updated depending on the current state of the button, just like what's happening now, just without refreshing the dom, I know I should probably use something called axios but I didn't really understand how does it work, I also know I should work on my skills cause I have probably done a lot of mistakes, feel free to edit the whole thing if it's gonna work at the end, thanks for your time.

0 likes
4 replies
Yugi's avatar
Level 23

This is what I've done so far, which still does not work but it's in the general direction that I wanna go to, for some reason, @submit.prevent doesn't work, it worked for a couple of times but then the form went back to submitting as usual which is not desired,

this is the form now:

  <td> 
  <form method="POST" @submit.prevent="onSubmit" action="{{ route('course.completed', $course->name) }}" id="form-submit">
                     {{-- {{ method_field('PUT') }} --}}
                       {{ csrf_field() }}
 @if ($course->completed == true)
      <button type="submit" class="btn btn-sm" id="coursetogglingtrue">Done!</button>
@else
  <button type="submit" class="btn btn-sm" id="coursetogglingfalse">Not Yet!</button>
  @endif

    </form>
  </td>

Theses are the scripts inside app.blade:

    <!-- Scripts -->
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
    <script src="/js/app.js"></script>
    <script>
      new Vue({
          el: '#app',
          data: {
            course: ''
          },
          methods: {
            onSubmit() {
              // course = $event.target;
              axios.post('/MyCourses/{{course.name}}').then(console.log(course));
            }
          }
      });
    </script>

api.php and CoursesController are still the same, and I'm still frustrated, I watched the recommended videos, thought I understood what's going on but still, 0 progress, I want to have course be equal to whatever value of the request was, so that I can then target the value of the name of the course that was submitted, but I'm not sure how to do that, I tried a few different things, all failed.

spekkionu's avatar
axios.post('/MyCourses/{{course.name}}').then(console.log(course));

The vue template syntax will only work in the template part and not in the javascript itself.

Also without prepending with @ it will be parsed by blade which will try to concatenate the constant course with the constant name.

Also the then function should be a callback. What you have will pass in the result of the console.log.

You are also not passing the course to Vue either by pulling it via ajax or by binding it with v-model or passing it as a prop so the course in the vue data will always be an empty string.

2 likes
Yugi's avatar
Level 23

You gave me some important insights, I'm done with the ajax part and I'm almost there with the rest I just need to do a few things, this is what I've managed to do so far,

In the view:

  <form method="POST" @click.prevent="onSubmit" action="{{ route('course.completed', $course->name) }}" id="form-submit">
                       {{ csrf_field() }}
     @if ($course->completed == true)
     <button type="button" class="btn btn-sm" id="coursetogglingtrue">Done!</button>
     @else
     <button type="button" class="btn btn-sm" id="coursetogglingfalse">Not Yet!</button>
     @endif 

Changing the type of the button from submit to button allowed the .prevent method to actually fire, now the form doesn't submit anymore, the form still needs work in order to output the proper class depending on the status of the course but regardless,

This is the script that I have now:

    <script>
      new Vue({
          el: '#app',
          data: {
            course: {
              name: '',
              bool: false
            }
          },
          methods: {
            onSubmit: function() {
              this.course.bool = !this.course.bool,
              axios.post('/MyCourses/{{$course->name}}')
                   .then(function (response){
                      // {{$course->completed}} = response.course.completed;
                   });
            }
          }
      });
    </script>

Somehow right now, I'm actually sending the post request to the correct route, but there's a problem which has the highest priority right now, $course is referencing the latest course that was added to the page, and not the course that I chose by pressing on the button, now whichever button I press, the last course gets injected to $course, and then ofc to the route in axois, I don't know how to figure that out yet, but so far that course gets updated, and if I inspected the network tab in chrome, I see the response and that value of the completed column gets updated, I believe that there are still some mistakes in the code, but I'll keep trying, if you can point out some more things please let me know, thanks

Please or to participate in this conversation.