1

I have some JavaScript that works with jQuery.validate. This takes a JSON object that comes back from the server, and passes it to the showErrors function. The response.errors object looks like this...

{[
  { item1: "Email", item2: "Invalid format" },
  { item1: "ExpiryDate", item2: "Must be in the future" }
]{

The following ES6 code works fine...

for(var i = 0; i < response.errors.length; i++) {
  $('form').validate()
    .showErrors({ [response.errors[i].item1]: response.errors[i].item2 });
}

However, I've just discovered that IE doesn't support ES6, so this doesn't work there. I tried using es6-shim (and es-5shim), but it didn't help.

I've been trying to write some ES5-compatible code to do the same thing, but have failed at every attempt. I have looked at answers such as this one and this one, but I just can't get anything to work.

My latest attempt was the following...

var error = {};
error[response.errors[i].item1] = response.errors[i].item2;
$('form').validate().showErrors(error);

However, despite the fact that dumping error and the previous code to the console showed them to be identical, when I try to use this code, I get an error in the console...

Uncaught (in promise) TypeError: Cannot read property 'type' of undefined at $.validator.highlight (jquery.validate.js:344) at $.validator.defaultShowErrors (jquery.validate.js:912) at $.validator.showErrors (jquery.validate.js:546) at handleServerResponse (Donate:305)

The line in question is the one where I call showErrors

Anyone able to help me?

Update just to clarify, the reason I'm doing this in a loop is that the server-side code returns three types of errors, normal ones related to a specific input element, general ones relating to the data as a whole, and ones specific to a payment section of the form. I only pass the first type to jQuery.validate, as the second type are displayed in an independent part of the form, and the third type have to be handled differently as the payment processor generates its own HTML in an iframe, meaning I have to add the error manually.

Second update Turns out that it was some code on a separate part of the page that was throwing out my JavaScript. The code I had, and that shown in the two answers was fine, it was a separate problem.

DreamingOfSleep
  • 1,208
  • 1
  • 11
  • 23
  • 1
    it's not the problem in your code, the library you are using here `jquery.validate.js` is creating the error, maybe it's written in es6 – Shridhar Sharma May 22 '19 at 15:28

2 Answers2

4

To build the object you can use a loop through the array you receive from the AJAX request, then by using bracket notation to add properties to the object, you can pass it to showErrors(), something like this:

var errors = {};
response.errors.forEach(function(err) {
  errors[err.item1] = err.item2
});
$('form').validate().showErrors(errors);
Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
  • 1
    @adiga The [`showErrors` method takes an object](https://jqueryvalidation.org/Validator.showErrors/) with key/value pairs that are the input names and messages to show. – Heretic Monkey May 22 '19 at 15:34
  • 1
    @HereticMonkey okay. Just mentioned since OP said the ES6 code with multiple calls to `.showErrors()` was working fine. – adiga May 22 '19 at 15:38
  • @Rory Thanks, but this was one of the things I tried, and got the error I mentioned. I dumped the `errors` object to the console, and it looked fine. This was where I got stuck. Any ideas? Thanks again – DreamingOfSleep May 22 '19 at 16:17
  • 1
    Given the information you've shown in the question this solution works: https://jsfiddle.net/w9Ldesh3/. Note that I did fix some syntax issues in the Object you showed though, as it was invalid. Perhaps check the console to ensure there's no other syntax errors – Rory McCrossan May 22 '19 at 16:22
  • @RoryMcCrossan As you can see from my updated answer, the code you showed worked fine, the problem was elsewhere. It was hard to choose between your answer and Heretic Monkey's, but I chose yours for its simplicity. – DreamingOfSleep May 22 '19 at 21:48
1

Similar to Rory's answer, but I would use reduce to take the response.errors array and transform it to one with the properties in the right place.

Note that the showErrors method takes an object with key/value pairs that are the input names and messages to show, so you don't need to call it in the loop.

var errors = [
  { item1: "Email", item2: "Invalid format" },
  { item1: "ExpiryDate", item2: "Must be in the future" }
];

var errorsToShow = /*response.*/errors.reduce((arr, cur) => { 
  arr[cur.item1] = cur.item2; 
  return arr; 
}, {});

console.log(errorsToShow);

// $('form').validate().showErrors(errorsToShow);

The error you're seeing likely occurs here, in jquery.validate.js (this link goes to the source that makes up that file):

    highlight: function( element, errorClass, validClass ) {
        if ( element.type === "radio" ) {
            this.findByName( element.name ).addClass( errorClass ).removeClass( validClass );
        } else {
            $( element ).addClass( errorClass ).removeClass( validClass );
        }
    },

It's looking for the type property on an HTMLInputElement, but element is undefined.

You can fix this in at least two ways:

  1. By ensuring that the errors you pass in the object are only for those where item1 (the key of the object's property) refers to a named element (or have those that are not marked in some fashion so that you can filter them out). This would be the preferred and cleanest way of doing it.
  2. By providing your own highlight function (if you are unable to change the API for some reason). Apparently jQuery Validation allows for passing in overrides to some of their functions, so you can call validate() with options and in those options pass your own highlight function. Perhaps one that starts with:

    if (!element) return;
    

    I would suggest also implementing the unhighlight function since it has similar code. This is not the preferred option, because you're just putting a bandage over the "real" problem, which is that you're asking showErrors to show errors that don't exist (to the jQuery Validation plugin). You could also just overload showErrors, but that gets a bit more involved.

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
  • Thanks for the reply, but this didn't work. Please see my comment on Rory's answer. I also updated the question to explain why I'm using a loop. Thanks anyway, any more ideas? – DreamingOfSleep May 22 '19 at 16:25
  • 1
    Well, it's not very fair to ask a question, then change the question from under the existing answers, is it? – Heretic Monkey May 22 '19 at 16:29
  • Sorry, didn't intend to change the question. All I did was explain why I'm using a loop. I don't see that it's actually relevant to my problem, as I get the same issue if I use your or Rory's code to create an object and pass that in to `showErrors` in one go. – DreamingOfSleep May 22 '19 at 16:41
  • Thanks again for he help, as you can see from my updated question, the problem was elsewhere. – DreamingOfSleep May 22 '19 at 21:49