stratboy's avatar

How to retrieve the error messages text when receiving a json 422 response?

Hi, I'm working on a form sent via fetch, and the error I receive is like

{
  "status": 422,
  "errors": {
    "message": "validation.required",
    "errors": {
      "name": [
        "validation.required"
      ]
    }
  }
}

Now, those seem more keys than real messages. I can see that in /lang/en/validation.php we've got a 'required' message that reads like 'The :attribute field is required.' How do I pick that in js?

0 likes
6 replies
LaryAI's avatar
Level 58

To retrieve and display the error messages from a JSON 422 response in JavaScript, you can follow these steps:

  1. Parse the JSON response to extract the error keys.
  2. Map these keys to the actual error messages defined in your validation.php file.
  3. Display the error messages to the user.

Here's a step-by-step solution:

  1. Fetch the JSON response and parse it:
fetch('/your-endpoint', {
  method: 'POST',
  body: JSON.stringify(yourFormData),
  headers: {
    'Content-Type': 'application/json'
  }
})
.then(response => {
  if (!response.ok) {
    return response.json().then(errorData => {
      throw errorData;
    });
  }
  return response.json();
})
.then(data => {
  // Handle success
})
.catch(errorData => {
  if (errorData.status === 422) {
    handleValidationErrors(errorData.errors);
  } else {
    // Handle other errors
  }
});
  1. Map the error keys to the actual error messages:

You need to have a mapping of your validation keys to the actual messages. This can be done by creating a JavaScript object that mirrors your validation.php file.

const validationMessages = {
  'validation.required': 'The :attribute field is required.',
  // Add other validation messages here
};

function getErrorMessage(key, attribute) {
  let message = validationMessages[key];
  if (message) {
    return message.replace(':attribute', attribute);
  }
  return 'An error occurred';
}
  1. Handle and display the validation errors:
function handleValidationErrors(errors) {
  const errorMessages = [];
  for (const [field, messages] of Object.entries(errors.errors)) {
    messages.forEach(messageKey => {
      const errorMessage = getErrorMessage(messageKey, field);
      errorMessages.push(errorMessage);
    });
  }
  displayErrors(errorMessages);
}

function displayErrors(errorMessages) {
  const errorContainer = document.getElementById('error-container');
  errorContainer.innerHTML = '';
  errorMessages.forEach(message => {
    const errorElement = document.createElement('p');
    errorElement.textContent = message;
    errorContainer.appendChild(errorElement);
  });
}
  1. HTML to display errors:

Make sure you have an element in your HTML to display the error messages:

<div id="error-container"></div>

Putting it all together, your JavaScript code will fetch the response, handle the validation errors by mapping them to user-friendly messages, and display them in the designated HTML element. This approach ensures that your users see meaningful error messages instead of cryptic validation keys.

jlrdw's avatar
            try {
                //alert("here");
                const response = await fetch(url, {
                    method: "PUT",
                    headers: {
                        'Accept': 'application/json',
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify(data),
                });
                if (!response.ok) {
                    const json = await response.json();
                    showFetch(json);   ///To display actual error messages
                    throw new Error(`Response status: ${response.status}`);
                } else {
                    const json = await response.json();
                    showFetch(json);   // will show "all okay"
                    console.log(json);
                }


            } catch (error) {
                console.error(error);
            }
        function showFetch(data) {
            var div = document.getElementById('msg');
            document.getElementById("msg").style.display = "block";
            for (var key in data) {
                div.innerHTML += " " + data[key];
            }
        }
        $validator = \Illuminate\Support\Facades\Validator::make($request->all(), [
                    'species' => 'required',
                    'sex' => 'required',
        ]);

        if ($validator->fails()) {
            return Response::json($validator->errors(), 422);
        }

code

return Response::json(['success' => 'all okay']);

I wasn't kidding, you will find Axios JS so much easier to use.

Link I gave in your other question had an example.

1 like
jlrdw's avatar

@stratboy Axios example:

                    .then(function (response) {
                        //console.log(response.data);
                        var data = response.data;
                        if (response.status > 199 && response.status < 210) {
                            showData(data);
                        }
                    })
                    .catch(error => {
                        if (error.response) {
                            showData(error.response.data);
                        }
                    });

And the function:

        function showData(data) {
            var div = document.getElementById('msg');
            document.getElementById("msg").style.display = "block";
            for (var key in data) {
                div.innerHTML += " " + data[key];
            }
        }

You don't have to mess with headers, stringify, etc if using json.

Get axios direct, https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js

Save file and then just:

<script type="text/javascript" src="<?php echo asset('assets/js/axios.min.js'); ?>"></script>

But where ever or however you load assets.

Otherwise most use NPM. I don't.

https://axios-http.com/docs/intro

Takes about 45 seconds to start using axios.

2 likes
stratboy's avatar

@jlrdw I also tried Axios, and it's slighty less verbose like you said. Adds about 12kb to gzipped js, it's ok anyway. Not that much difference but nice. Thank you.

stratboy's avatar

In fact, the issue was only the lang files. My APP_LOCALE was 'it', and I didn't have a /lang/it dir. Therefore the app didn't return the values. Now I created the 'it' dir and translated the relevant message and it's working fine.

{
  "message": "Il campo name è obbligatorio. (and 1 more error)",
  "errors": {
    "name": [
      "Il campo name è obbligatorio."
    ],
    "description": [
      "Il campo description è obbligatorio."
    ]
  }
}
1 like

Please or to participate in this conversation.