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.
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" @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>
For some reason the @submit.prevent method is not working, it worked a couple of times but then It just didn't, and the form kept submitting as usual.
These are the scripts inside app.blade.php, I don't know how/where should I compile this, it's just sitting there in the main layout of my project, should I transfer it to public/js/app.js? or compile it using gulp? if you have something in mind please let me know:
<!-- 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>
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 and inject it to the route as I'm trying to do, but I'm not sure how to do that, I tried a few different things, all failed. And here is routes/api.php
Route::post('/MyCourses/{name}', 'CoursesController@toggling')->name('course.completed');
ofc right now this is not working, the form is submitting, and I'm redirected to a route where I get back the json response, and that's it, I just want to refresh the dom so that the button would have the new id depending on that status of the course, and the course itself to be updated and saved in the background without refreshing the page. I am fairly new to this, I understand that the form should probably be re-written, and I know I've done a lot of mistakes, but I just want it to work, so help would be very appreciated.
UPDATE
After a lot of hours of trial and error, 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
An improvement to the answer above would be to use Template Literals introduced in ES6.
Instead of:
axios.post('/MyCourses/' + course.name).then(console.log(course));
You can do:
axios.post(`/MyCourses/${course.name}`).then(console.log(course));
More information on Template Literals functionality and syntax can be found here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
The syntax you are using is wrong in following line:
axios.post('/MyCourses/{{course.name}}').then(console.log(course));
It should be :
axios.post('/MyCourses/' + course.name).then(console.log(course));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With