简体   繁体   中英

jQuery validator on array of select elements with custom validation infinite loop

I have a fiddle here with my issue.

I have a range of selects in a form, all with name player[] . I want to check these for:

  1. All required
  2. There are at least 2 item.val() !== "none"
  3. At least one item.text() === "me"

My validator custom rules are:

var form = $("#player_form");

$.validator.addMethod(
  "minPlayers",
  function(value, element, requiredValue) {
    var noPlayerCount = 0;
    $("[id^=player-]").each(function(i) {
      if (($(this).find('option:selected').val() !== 'none') && ($(this).find('option:selected').val() !== '')) {
        noPlayerCount++;
      }
    });
    if (noPlayerCount < requiredValue) {
      return false;
    }
    return true;
  },
  "You need more than 1 player for a game"
);

$.validator.addMethod(
  "mePlayer",
  function(value, element, requiredValue) {
    var meCount = 0;
    $("[id^=player-]").each(function(i) {
      if ($(this).find('option:selected').text() === 'me') {
        meCount++;
      }
    });
    if (meCount !== requiredValue) {
      return this.check($('#player-1'));
    }
    return this.valid();
  },
  "You need to be in the game"
);

form.validate({
  rules: {
    game_name: {
      required: true,
      maxlength: 14
    },
    difficulty: {
      required: true
    },
    'player[]': {
      required: true,
      minPlayers: 2,
      mePlayer: 1
    }
  },
  messages: {
    game_name: {
      required: "Name your game",
      minlength: $.validator.format("Your game name can be a max of {0} chars")
    },
    difficulty: {
      required: "Please select a difficulty"
    },
    'player[]': {
      required: "A player cannot be blank"
    }
  },
  submitHandler: function(form) {
    alert("SUBMITTED!");
    return false;
  }
});

This code runs into a infinite loop / max stack size. What did I miss? Thanks!

I fixed a couple things...

In HTML: selected='' isn't good. This attribute is a boolean. Missing, it is false and present it is true... And can be setted to true/false, but not as empty.

In JS:

$("[id^=player-]").each(function(i) { loop all elements having an id starting by player- . You had 8 player-n and 8 player-nickname-n . So it was counting up to 16 players.

When checking the option's text like if ($(this).find('option:selected').text() === 'me') { , if the text is "Me", it returns false. That is case sensitive.

And finally, whatever you do in the function you provide to .addMethod as second argument, it must return a true or a false. Trying to return something else lead to infinite loop.... Don't ask me why exactly.

So here is your code fixed, I left all console log I used to debug.

var form = $("#player_form");

$.validator.addMethod(
  "minPlayers",
  function(value, element, requiredValue) {
  console.log("requiredValue1: "+requiredValue);
    var noPlayerCount = 0;
    $("[id^=player-]").each(function(i) {
      console.log ("option value: "+$(this).find('option:selected').val());

      if (($(this).find('option:selected').text() !== 'None')){ //} && ($(this).find('option:selected').val() !== '')) {
        noPlayerCount++;
      }
    });

    console.log("noPlayerCount: "+noPlayerCount);
    if (noPlayerCount < requiredValue) {

      return false;
    }
    return true;
  },
  "You need more than 1 player for a game"
);

$.validator.addMethod(
  "mePlayer",
  function(value, element, requiredValue) {
  console.log("requiredValue2: "+requiredValue);
    var meCount = 0;
    $("[id^=player-]").each(function(i) {
      if ($(this).find('option:selected').text() === 'Me') {    // Capital "M"
        meCount++;
      }
    });
    if (meCount !== requiredValue) {
      return false; //this.check($('#player-1'));     // Validator must return true or false.
    }
    return true;  //this.valid();                     // Validator must return true or false.
  },
  "You need to be in the game"
);

form.validate({
  rules: {
    game_name: {
      required: true,
      maxlength: 14
    },
    difficulty: {
      required: true
    },
    'player[]': {
      required: true,
      minPlayers: 2,
      mePlayer: 1
    }
  },
  messages: {
    game_name: {
      required: "Name your game",
      minlength: $.validator.format("Your game name can be a max of {0} chars")
    },
    difficulty: {
      required: "Please select a difficulty"
    },
    'player[]': {
      required: "A player cannot be blank"
    }
  },
  submitHandler: function(form) {
    alert("SUBMITTED!");
    return false;
  }
});

$("#my_button").click(function() {
  var form = $("#ajax_login_form");
  form.validate();
})

Updated Fiddle

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM