Inertia - Reloading page url created with POST shows GET 405 (Method Not Allowed) - laravel

I want to load a new vue component and show its id in the URL. This can be done like so:
<template>
<button #click="submit">Load new page with id in url</button>
</template>
<script>
import {Inertia} from "#inertiajs/inertia";
const submit = () => {
const id = 1
Inertia.post('/admin/kreationen/bearbeiten/' + id, {id: id})
}
</script>
and on the laravel side (web.php):
Route::post('/admin/kreationen/bearbeiten/{id}', function (Request $request) {
return inertia('backend/cms-gallery-edit', ['id' => $request->id]);
});
Problem is, when I am reloading the page, this error is shown:
GET http://127.0.0.1:8000/admin/kreationen/bearbeiten/1 405 (Method Not Allowed)
I understand why this error is happening but how would I achieve the goal of showing the id in the new url without getting this error?
Edit:
I don't know why my original approach didn't work yesterday but now it does. For anyone interested:
<inertia-link :href="'/admin/kreationen/bearbeiten/' + data['id']">
<button>Load new page with id in url</button>
</inertia-link>
backend:
Route::get('/admin/kreationen/bearbeiten/{id}', function (Request $request) {
return inertia('backend/cms-gallery-edit', ['id' => $request->id]);
});

Probably you needed to use GET Request instead of POST Request. If yes, then just add to url your id and then pass the GET method to param:
const id = 1
Inertia.visit('/admin/kreationen/bearbeiten/' + id, {method: 'get'})
And for Backend side in Laravel url stays as it is, but recieved parameter is only $id and method needs to change to GET:
Route::get('/admin/kreationen/bearbeiten/{id}', function ($id) {
return inertia('backend/cms-gallery-edit', ['id' => $id]);
});
The 405 (Method Not Allowed) occurs when you try to load the POST methoded url via GET method and vice versa.
So first when you click, the post method is working fine, but when you reloading the page, it counts as GET method (just like direct opening the page). So recieving 405 error is fair, if you are able to use GET method to your needs, then use GET method (if you are ok with whenever user accesses the page directly without any form posted).
If not, then you might firstly do you POST requests in different route, then redirect user to another route (To prevent re-sending form when reloading the page, but to opening another page with some form data (ofcourse it must be saved somewhere like session or db))

Related

Inertia.JS reload props after post request

I am currently pretty confused why Inertia.js is not reloading or rerendering my page.
I have a form that could be filled, once submitting this will execute:
Inertia.post("/ban", ban);
This will redirect to a POST in the web.php of my Laravel.
That looks like this:
Route::post("/ban", [Speler::class, "ban"]);
This redirects to a class called "Speler", in there is a function called "ban".
Once done some SQL statements it will execute this return:
return Redirect::route("speler", [$steam])->with("success", "Ban doorgevoerd!");
This will go back to the web.php, and go to the route speler with the session data "success".
That redirect goes into the web.php:
Route::get("/speler/{steam}", [PageLoader::class, "speler"])->name("speler");
This one goes to the PageLoader controller, and execute the "speler" function.
But here it gets weird, this will return a Inertia::render of the same page the person was on, but would need to add another prop, or change the prop. (so i can show a popup with te text that it succeeded)
return Inertia::render("Panel/Speler",
["steamNaam" => $steamNaam, "discord" => $discord, "karakterAantal" => $karakterAantal, "karakters" => $karakters, "sancties" => $sanctiesReturn, "punten" => $aantalPunten, "steamid" => $steamid, "success" => $melding]
);
The "success" prop contains $melding that simply contains a string.
But for some reason it doesn't seem to re-render the page, the form stays filled, and the props are the same.
Does someone have a solution?
If you setup your form with the form helper, you can reset the form on a successful post like this:
form.post('/ban', {
preserveScroll: true,
onSuccess: () => form.reset(), // reset form if everything went OK
})
The success message, which you set with
return Redirect::route("speler", [$steam])->with("success", "Ban doorgevoerd!");
is usually taken care of by the Inertia middleware and made available as 'Shared data'. See this docs page on how to configure that. Shared data is rendered in $page.props variable. That is where you can find the Ban doorgevoerd! message. You can show these to the user as follows:
<div v-if="$page.props.flash.message" class="alert">
{{ $page.props.flash.message }}
</div>
Depending on your implementation, you would need to watch this property. See the FlashMessages component on the pingCRM demo app for an example implementation.

Difference between update and editing in controller - laravel

My table has the option edit. A row can be updated and saved to the database. While I was trying to implement this option I came across uncertainty. What do I have to do with the data from my edited row when it arrives at my controller? It doesn't seem clear to me do I have to use the edit, the update or combine them both? Do I need edit to find the id of the row that needs to be updated?
I am using the following code in methods to send data to my controller
<template slot="actions" slot-scope="row">
<span #click="updateProduct(row.item);" class="fas fa-pencil-alt green addPointer"></span>
</template>
updateProduct: async function(productData) {
axios.post('/product/update', {
productData: productData
.catch(function(error){
console.log(error)
})
})
}
In my controller, I think I have to find the id. I am pretty sure I am confusing different methods together. Thanks for any input.
public function edit()
{
$product = Product::with('id')->find($id);
// do something with it
}
public function update(Request, $request){
$product->update([
'name' => $request->productData->Name,
'description' => $request->productData->Descr
]);
}
the difference is significant. Edit is for displaying a form to apply changes and Update is used to set them up to server.
Edit is via GET http Update is via PUT http
In Laravel resource controller you can see these two functions "edit" & "update"
For example, you have a resource route 'post'
Edit:
you can return your edit form with your previously stored data
you can call using GET method & URL will be "/post/{id}/edit" and the route will be "post.edit"
update:
you can submit your data which you want to update
you can call using PUT/PATCH method & URL will be "/post/{id}" and the route will be "post.update"
For more information refer : laravel.com -> controllers

Spring-Boot: Redirect and Refresh model and page

I have a spring-boot application, with theyemleaf. I repeatedly update the page, and redirect it to the same page, so i expect that the elements of the page get updated:
#GetMapping("/suggested-events/vote/{eventId}")
public String voteForEvents(Model model,
#PathVariable("eventId") Long eventId,
#RequestParam(value = "message", required = false) String message ) {
log.info("The message is: "+message);
SuggestedEvent event = suggestedEventService.findSuggestedEventById(eventId);
ArrayList<SuggestedEvent> events = suggestedEventService.findSuggestedEventsByArea(event.getArea());
model.addAttribute("mainEvent",event);
model.addAttribute("events",events);
model.addAttribute("message",message);
return "/suggested-event/vote";
}
and when a button get pushed in the view it triggers the below post method:
#PostMapping("/suggested-events/vote")
public String voteForASuggestedEvent(RedirectAttributes redirectAttributes){
log.info("You have made a vote");
redirectAttributes.addAttribute("message", "Success");
return "redirect:/suggested-events/vote/1";
}
This second controller method, performs an operation an makes a message, and redirects it to the first method. So, it successfully redirected to the first method and it logs
log.info("The message is: "+message);
but it does not refresh my page, and i do not get the message as model?
When i redirect to the first method, i expect it adds the message to my models:
model.addAttribute("message",message);
But it does not added to my page
and when a button get pushed in the view it triggers the below post
method:
It sounds like this trigger is using AJAX, rather than a form submit. Doing so would match the symptoms you describe.
If you POST to /suggested-events/vote using AJAX, the server will return a 302, and the browser will follow it. However, the response for that 302 is still the result of an AJAX call. You have access to it in your success callback, but the browser isn't going to render it for you.
but it does not refresh my page
If a 302 doesn't cause your page to re-render, this also suggests you're using AJAX.
If you actually use a form submit instead, the browser will re-render using the markup returned by the successful redirect.
This can be verified by using the following two buttons in your vote.html:
<form action="http://localhost:8080/suggested-events/vote" method="POST">
<input type="submit" text="Submit" />
</form>
<button onclick="postmessage();" >Button</button>
<script>
function postmessage() {
$.ajax({
method: 'POST',
data: {},
url: 'http://localhost:8080/suggested-events/vote'
});
}
</script>
The first button will work as expected, and the second button matches the symptoms you describe.
If you are already using a form, please update the question with it (or better yet, the entire Thymeleaf template).
I had the same problem as OP described and Mike's explanation brought me in the right direction.
I am reading a db-table and populating it with thymeleaf using th:each. I wanted to add a javascript-confirmation before deleting an item. Sending an ajax GET without an event-listener and reloading with location.reload(true) didn't reach the #GetMapping("/delete/{id}") in the controller.
This SO-thread gave me the answer to the ajax-call.
<a class="btn btn-danger" href="#" th:onclick="|confirmDeletion('${u.id}')|"></a>
<script th:inline="javascript">
function confirmDeletion(id) {
if (confirm("Delete this id? " + id)) {
var http = new XMLHttpRequest();
http.open("GET", "/delete/" + id, true);
http.addEventListener("readystatechange", function() {
if (http.readyState === 4 && http.status === 200) {
window.location.reload(true);
}
});
http.send();
}
}
</script>
there are many ways to redirect page in Spring, but be sure if the model attribute off message its passing correctly to FrontEnd or passing like parameter to another handler , you can see this document : http://javainsimpleway.com/spring-mvc-redirecting-model-attributes-from-one-controller-to-other-controller/ , hope this is useful !!

Laravel: controller not teletransporting me (redirect-ing me) to the page

from Ajax the controller does get the keyword I want, as it confirms it (because I echo it), and my idea was that on getting that keyword, it should redirect to the page I want. Yet, it does not, and also, while it does change the locale, I have to reload the page, otherwise, it won't show any translation and locale changes on the page. In Firebug when I hover over the POST, I get the correct URL to where I would want to go: sort of http://myweb.com/es but the controller does not change the http URL box of my browser on my web to go there.
I am simplifying the Controller code here, but actually I will want it to go to different URLs depending on the keyword it gets, something that I would do with a switch statement or IF else if etc.
So the controller is as simple as this:
public function changelanguage()
{
$lang = \Input::get('locale');
echo "I got $lang";
Session::put('locale', $lang);
return redirect('/es');
}
If instead of using ajax I use a Form, then I dont need to reload, the Action of the form makes the controller change the locale and translate the page without reloading. But I need to use ajax and in any case, the controller does get correctly the keyword ('en', 'es', 'de' etc ) for languages, so it should take it from there and redirect me to the URL page, but it just doesnt move.
if you are curious about the Ajax, here it is, but it does send the keyword as I said.
$(document).ready(function(){
$('.choose-language').on('click', function(e){
e.preventDefault();
var selectedlanguage = $(this).data('value');
$.ajax({ // so I want to send it to the controller
type:"POST", // via post
url: 'language',
data:{'locale': selectedlanguage},
}); // HERE FINISHES THE $.POST STUFF
}); //HERE FINISHES THE CLICK FUNCTION
}); // HERE FINISHES THE CODE
ROUTES
Route::post('language', array(
'as' =>'language',
'uses' => 'LanguageController#changelanguage'
));
If you’re trying to perform the redirect in the AJAX-requested script, then it won’t work. You can’t redirect from a script request via AJAX otherwise people would be doing all kinds of nefarious redirects.
Instead, set up a “success” handler on your AJAX request that refreshes your page if the request was successful. It can be as simple as:
var url = '/language';
var data = {
locale: $(this).data('value');
};
var request = $.post(url, data)
.success(function (response) {
// Script was successful; reload page
location.reload();
});
I’m not sure how you’re allowing users to select locales, but since you need a reload any way I think AJAX is pointless here. Just have a traditional form that submits the new locale to an action, set the locale in a session/cookie/whatever, and then redirect back to the referring page.

Laravel 4.0 Filter and Ajax to load a bootstrap modal pop up

I'm doing a website based laravel 4.2 and Bootstrap. I want a bootstrap modal pop up dialog to load on certain routes provided that the user is not already logged in.
So far i have accomplsihed it to load for the entire application upon loading which is not i want but am in the right direction.
This is my ajax call
script type="text/javascript"> $(document).ready(function() {
$.get("status", function(data, status){
data.status == false ? $('#modal-form').modal({backdrop: 'static'}) : $('#modal-form').modal('hide');
});
});
Status refers to a URL defined in this route
Route::get('/status', 'LoginController#getLoginStatus');
and the method is defined here
public function getLoginStatus()
{
return Response::json(array( 'status' => Sentry::check()));
}
From that, the modal dialog loads on each route across the entire application. I would want to limit the dialog to load on certain routes provided the user is not logged in.
Thing Laravel filter would do the trick for me but i have failed to do so.
Something like
Route::filter('status', function()
{
});
and then the route be like:
Route::get('profile', array('as' => 'submit-profile','before' => 'status','uses' => 'ProfileController#getProfile'));
Thanks guys hope you can give me some advice.
You could use the
Route::currentRouteName()
to check what route your on and then do your preferred action,
like calling the ajax get request for the modal.

Resources