stratboy's avatar

Why isn't validate() giving me an error and 422 status?

Hi, I'm trying to test vaidation when sending requests with the Fetch API (ajax). But it seems it always validates despite for example, leaving empty a required field. My current php code in brief:

  public function store(Request $request){

    $validatedData = $request->validate([
      'name' => 'required'
    ]);

    return response()->json(['success' => true]);
}

And js:

seed_form.addEventListener('submit', function(e){

  e.preventDefault();
  const headers = new Headers();
  headers.append("X-CSRF-TOKEN", csrf_token[0]);

  let form_data = new FormData(seed_form);
  if(page == 'edit') form_data.append("_method", 'PUT');

  submit_button.disabled = true;
  spinner.classList.add('visible');

  let route = (page == 'create') ? '/semi' : `/semi/${seed_id}`;

  fetch(route, {
    method: 'POST',
    body: form_data,
    headers: headers
  }).then((response) => {
    console.log('response', response);
    if(!response.ok){ throw new Error(`HTTP error, status = ${response.status}`); }
    //return response.json();
  }).then((data) => {
    console.log('data', data);
  }).catch(async (error) => {

    if (error.status === 422) {
      const errorData = await error.json();
      console.log(errorData);

    } else {
        console.error('Error:', error);
    }

  });

});

In fact, what I keep getting back is a response with 200 status code, so the catch block is never executed.

Why?

0 likes
7 replies
LaryAI's avatar
Level 58

The issue you're encountering is likely due to the fact that Laravel's validation errors are not being properly caught and handled in your JavaScript code. When validation fails, Laravel will return a 422 Unprocessable Entity status code along with the validation errors. However, your JavaScript code is not set up to properly handle this scenario.

Here's a step-by-step solution to address this:

  1. Ensure Laravel is returning a 422 status code on validation failure:

    Your Laravel controller method looks correct, but make sure that the validation rule is being applied correctly. If the name field is empty, Laravel should automatically return a 422 status code with the validation errors.

  2. Update your JavaScript code to handle the 422 status code properly:

    You need to modify your JavaScript code to handle the 422 status code and parse the response JSON to get the validation errors.

Here is the updated JavaScript code:

seed_form.addEventListener('submit', function(e) {
  e.preventDefault();
  const headers = new Headers();
  headers.append("X-CSRF-TOKEN", csrf_token[0]);

  let form_data = new FormData(seed_form);
  if (page == 'edit') form_data.append("_method", 'PUT');

  submit_button.disabled = true;
  spinner.classList.add('visible');

  let route = (page == 'create') ? '/semi' : `/semi/${seed_id}`;

  fetch(route, {
    method: 'POST',
    body: form_data,
    headers: headers
  }).then((response) => {
    if (!response.ok) {
      if (response.status === 422) {
        return response.json().then((errorData) => {
          throw { status: 422, errors: errorData };
        });
      } else {
        throw new Error(`HTTP error, status = ${response.status}`);
      }
    }
    return response.json();
  }).then((data) => {
    console.log('data', data);
    // Handle success response
  }).catch((error) => {
    if (error.status === 422) {
      console.log('Validation errors:', error.errors);
      // Handle validation errors
    } else {
      console.error('Error:', error);
    }
  }).finally(() => {
    submit_button.disabled = false;
    spinner.classList.remove('visible');
  });
});

Explanation:

  1. Check for 422 status code:

    • In the .then block, if response.ok is false and the status is 422, parse the response JSON to get the validation errors and throw an error object containing the status and errors.
  2. Catch block:

    • In the .catch block, check if the error status is 422 and log the validation errors. Otherwise, log the general error.
  3. Finally block:

    • Re-enable the submit button and hide the spinner regardless of the outcome.

This should ensure that your JavaScript code properly handles validation errors returned by Laravel and logs them to the console.

stratboy's avatar

Mmm no Lary's code won't work since I'm getting back an:

Error: SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data

And that's because apparently Laravel is sanding me back a web page.

stratboy's avatar

@jlrdw Turns out that adding headers.append("Accept", "application/json"); was enough. No need for Axios then.

1 like
martinbean's avatar
Level 80

@stratboy If you want JSON responses, then you need to request JSON responses. You need to add the following header to your request:

headers.append('Accept', 'application/json');
1 like

Please or to participate in this conversation.