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

jkew's avatar
Level 1

Do you know why the ajax part of the js is not working?

I have a multi step form. In step 1 the user needs to insert info like his name, surname, etc. When the user clicks in "go to step 2" is send an ajax post request to the controller method storeUserInfo to validate the information introduced by the user.

But the ajax is not working, the ajax part of the code is not executing do you know where is the issue?

step1 html:

<div class="tab-pane fade show active clearfix" id="step1" role="tabpanel" aria-labelledby="home-tab">
    <h6>User Info</h6>
    <form method="post" id="step1form" action="">
         {{csrf_field()}}
        <div class="form-group font-size-sm">
            <label for="name" class="text-gray">Name</label>
            <input type="text" required class="form-control"  value="{{ (\Auth::check()) ? Auth::user()->name : old('name')}}">
        </div>
        <!-- other form fields -->
        <input type="submit" id="goToStep2" href="#step2"
                class="btn btn-primary btn float-right next-step" value="Go to step 2"/>
    </form>
</div>

jQuery:

$('#goToStep2').on('click', function (event) {
    event.preventDefault();

    var custom_form = $("#" + page_form_id);

    $.ajax({
        method: "POST",
        url: '{{ route('products.storeUserInfo',null) }}',
        data: custom_form.serialize(),

        success: function (data, textStatus, jqXHR) {
            setTimeout(function () {
                window.location.reload();
            }, 3000);
        },
        error: function (data) {
            var errors = data.responseJSON;
            $.each(errors['message'], function (index, value) {

            });
        }
    });

    });
});

PaymentController method:

public function storeUserInfo(Request $request, $id, $slug = null){
        //dd($request);
        $request->validate([
            'buyer_name' => 'required|max:1|string',
            'buyer_surname' => 'required|max:255|string',
            'buyer_email' => 'required|max:255|email',
            'name_invoice' => 'required|max:255|string',
            'country_invoice' => 'required|max:100|string',
        ]);
        return redirect(route('products.presentPaymentMethods',['id' => $id, 'slug' => $slug]));

    }

Route for the post request:

Route::post('/product/{id}/{slug?}/payment/storeUserInfo', [
    'uses' => 'PaymentController@storeUserInfo',
    'as'   =>'products.storeUserInfo'
]);

0 likes
45 replies
jlrdw's avatar
url: '{{ route('products.storeUserInfo',null) }}',

redo this for starters, somthing like

url: 'products/storeUserInfo',   //format
public function storeUserInfo(Request $request, $id, $slug = null){

Use laravel normal request, not parameter passing here.

Like

$whatever = Request::input('whatever');
1 like
jlrdw's avatar

See updated reply, and run all without ajax first to ensure it works correctly.

1 like
jkew's avatar
Level 1

You are saying to have "public function storeUserInfo(Request $request){" instead of "public function storeUserInfo(Request $request, $id, $slug = null){"?

jlrdw's avatar

No have a use statement at top

use Illuminate\Support\Facades\Request;
public function storeUserInfo(){
$whatever = Request::input('whatever');
// other inputs
1 like
Cronix's avatar

422 usually means it failed validation, so the 'error' method of your ajax call get triggered. Try changing that method to just console.log(data); and check the console to see if the errors are returned.

Also, add datatype: 'json' to your ajax options.

But really, there is no point in using ajax for this if all you are going to do is reload the page in the success event. It defeats the whole purpose of using ajax, so you might as well just be using a regular form and no ajax.

1 like
jlrdw's avatar
data: custom_form.serialize(),

sends a regular request object, not parameters.

1 like
jkew's avatar
Level 1

Thanks, but I don't want to reload the page in each step. I'm using ajax to validate each step without refresh the page. Its just necessary to remove this "window.location.reload();"?

And relative to the output of "console.log(data);". I changed to "

error: function (data) {
      console.log(data);
 }

and it shows:

errors : {buyer_name: Array(1)} message : "The given data was invalid." proto : Object responseText : "{"message":"The given data was invalid.","errors":{"buyer_name":["The buyer name may not be greater than 1 characters."]}}"


So it should be because of the validation error.
jkew's avatar
Level 1

And is necessary to use that "public function storeUserInfo(){ $whatever = Request::input('whatever'); // other inputs"? Because I just want to validate the inserted data by the user in the storeUserInfo method, I just want to use the validator.

Snapey's avatar

Better to use the route helper as you had originally.

If you use a url like suggested url: 'products/storeUserInfo', then this is added to the current route because it does not start with / and therefore is taken as relative to the current page. @jlrdw should know this ;-)

Snapey's avatar

Take a step back and learn to use the developer tools in your browser.

These can show you if your code is being called (you can use a breakpoint also), can show you the URL being called (if any) and the data being posted to the server

https://youtu.be/x4q86IjJFag

1 like
Snapey's avatar

ok, so look at your route;

Route::post('/product/{id}/{slug?}/payment/storeUserInfo', [
    'uses' => 'PaymentController@storeUserInfo',
    'as'   =>'products.storeUserInfo'
]);

The route products.storeUserInfo needs an {id}

You also need a {slug}, but I note that you have it as optional. I'm not sure you can have optional parameters in the middle of a URL ?

If you don't need those parameters, remove them from the route?

1 like
jkew's avatar
Level 1

So in the payment.blade.php in the url " url: '{{ route('product.storeUserInfo',null) }}', " is necessary to add to the url also the id and slug?

The parameters are not optional to access the payment page is necessary to have the id and slug of the product selected in the previous page (product details page). That is, the multi step form is in this page with this url "http://store.test/product/1/product-y/payment".

But for the ajax post request your are saying that is not necessary the id and the slug and so the route can be just like below? It is that?

Route::post('/product/payment/storeUserInfo', [
    'uses' => 'PaymentController@storeUserInfo',
    'as'   =>'products.storeUserInfo'
]);
Snapey's avatar

yes, ok, the url is that way to access the payment page, is it necessary for the post also? Possibly for the id, probably not for the slug (only you can say)

You can pass both through to the form and insert them into the route

1 like
Snapey's avatar

when processing the form you still need to know what id it relates to

jkew's avatar
Level 1

In the step1 and step 2 is not necessary but then in the step 3 will be necessary to insert in some tables and is necessary to use the product id.

Snapey's avatar

so keep it in the url. you can insert it in blade instead of null

1 like
jkew's avatar
Level 1

Thanks, but to have the id in " url: '{{ route('products.storeUserInfo',null) }}'", what is necessary is to have in the controller method that returns the payment.blade.php view something to return also the product id?

jkew's avatar
Level 1

I already return in that method the view payment with the id and slug like "return redirect(route('products.payment',['id' => $id, 'slug' => $slug]));". So maybe is just necessary pass directly to the " url: '{{ route('products.storeUserInfo',null) }}'," the id?

Snapey's avatar

dont you have the id on the product model?

url: '{{ route('products.storeUserInfo', $product->id) }}'
jkew's avatar
Level 1

I return only the id with:

return redirect(route('products.payment',['id' => $id, 'slug' => $slug]));"

so the $product is not returned. So, it should work with:

"url: '{{ route('products.storeUserInfo', $id) }}'"

and the route:

Route::post('/product/{id}/payment/storeUserInfo', [
    'uses' => 'PaymentController@storeUserInfo',
    'as'   =>'products.storeUserInfo'
]);

right?

jlrdw's avatar

To me it is easier using only ajax techniques when using ajax, not mixing laravel parameter routing in. Parameters are for Pretty urls but Ajax doesn't need pretty urls just hardcore Ajax.

So either use completely laravel techniques in this case or choose to use Ajax. Just my opinion.

Snapey's avatar

I dont know the controller method that shows the form so cannot advise, but you should be passing the id through to the view.

jkew's avatar
Level 1

The controller method that shows the form do some stuff and then redirects the user to payment page where is the multi step form. The controller method that redirects to the payment page have some stuff and the redirect is like:

    return redirect(route('products.payment',['id' => $id, 'slug' => $slug]));
Snapey's avatar

It cannot just be a redirect, there should be a controller for that products.payment route that returns the view.

jkew's avatar
Level 1

I have a PaymentController that has the storeProduct() method that does some stuff and then redirects the view payment.blade.php.

jlrdw's avatar

You are doing a redirect in the middle of an Ajax call.

jkew's avatar
Level 1

I have a PaymentController, the storeProduct method redirects to the route and then the presentPaymentPage redirects to the view payment.blade.php that is the page that has the multi step form:


public function storeProduct(Request $request, $id, $slug = null){
        // some stuff and redirect to the route
        return redirect(route('products.payment',['id' => $id, 'slug' => $slug]));
    }
    public function presentPaymentPage(Request $request, $id, $slug=null){
       // soem stuf and redirect the view

        return view('products.payment',
            ['product' => $product, 'id' => $id, 'slug' => $slug]);
    }
Next

Please or to participate in this conversation.