4

When trying to catch my Laravel validation errors using javascript, it keeps giving me the data in html format rather than json format, my validation looks normal. note i am using vue.js 3 and if the validation passes the actual method in the controller works fine, this is just a validation catching issue.

$request->validate([
       'first_name' => ['required', 'string', 'min:3', 'max:255'],
       'last_name' => ['required', 'string', 'min:3', 'max:255'],
       'email' => ['required', 'email', 'min:3', 'max:255'],
       'message' => ['required', 'string', 'min:3']
   ]);

my fetch method is as follows:

fetch('/contact-us', {
            method: 'POST',
            headers: {
                'CONTENT-TYPE': 'application/json'
            },
            body: JSON.stringify(this.form)
        }).then((response) => response.text())
            .then((data) => {
                console.log(data);
                //data = JSON.parse(data);
            }).catch(function(error) {
            console.log('Error: ' + error);
        });

my web route is:

Route::post('/contact-us', [IndexController::class, 'contactForm']);

the error in html format is:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<link href="/css/app.css" rel="stylesheet" />
<script src="/js/app.js" defer></script>
</head>
<body>
<style>
body{
    margin: 0 !important;
    overflow-x: hidden;
}
.container {
    padding-top: 20px;
}
</style>
<div id="app" data-page="{&quot;component&quot;:&quot;ContactUs&quot;,&quot;props&quot;:{&quot;errors&quot;:{&quot;email&quot;:&quot;The email must be a valid email address.&quot;},&quot;csrf&quot;:&quot;tFYwkcZZhNfeb2WXDwdnSv4dchujDvSvLfFGhHW1&quot;},&quot;url&quot;:&quot;\/contact-us&quot;,&quot;version&quot;:&quot;0f4e2ee0f7e2ca9da665d2f8035743df&quot;}"></div></body>
2
  • It's probably a token issue. Do you use Sanctum to authenticate your frontend app? Commented Feb 19, 2022 at 18:21
  • Its not an api, the site also has no login system. I have got it to work using the manual validation class and returning the json response manually, however this is not a good approach as it makes the controller look messy. Commented Feb 19, 2022 at 18:42

3 Answers 3

12

If you specify the Accept:application/json header in request, laravel will return json response

Sign up to request clarification or add additional context in comments.

2 Comments

Nope, not working for me.
Helped me! I was using '/' as Accept.
9

If validation fails during a traditional HTTP request, a redirect response to the previous URL will be generated.

If the incoming request is an XHR request, a JSON response containing the validation error messages will be returned.

First I suppose that /contact-us is a Web route and not an API route.

The $request->validate() default behavior on failure is to redirect you to the previous Web route with MessageBag.

To prevent that default behaviour, you need to wrap the validation process in a try-catch block and catch the Illuminate\Validation\ValidationException Exception and return error messages from [IndexController::class, 'contactForm'].

The the error messages array will automatically get converted to a JSON response.

try {
    $request->validate([
        'first_name' => ['required', 'string', 'min:3', 'max:255'],
        'last_name' => ['required', 'string', 'min:3', 'max:255'],
        'email' => ['required', 'email', 'min:3', 'max:255'],
        'message' => ['required', 'string', 'min:3']
    ]);
} catch (\Illuminate\Validation\ValidationException $th) {
    return $th->validator->errors();
}

Example respone:

{
    "first_name": [
        "first name field is required."
    ],
    "last_name": [
        "last name field is required."
    ],
    "email": [
        "L'E-mail field is required."
    ],
    "message": [
        "message field is required."
    ]
}

4 Comments

is there a way to swap it from XHR to fetch or add fetch to it?
@sgb999 when the documentation says XHR request that implicitly refers to JS fetch API that you used. Saying "I used XHR" or "I used the fetch API" can be used interchangeably. I guess that it is more interesting for to aim for using API routes instead of Web routes with your VueJS frontend
Also, did you disable the VerifyCsrfToken middleware? Because I see that you didn't include any token in your fetch()
It’s included in the form object i send.
2

The laravel docs days the response is given a 422 which throws an error in the usual error catch block. This data can be extracted by adding this catch error to your json post request

.catch(error => {
            if (error.response.data.errors) {
                console.log(error.response.data.errors);
            }
        });

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.