简体   繁体   中英

How can I make this javascript form validation DRYer?

The user has to select one radio from each of three input "categories". If he "submits" without doing so, he gets a warning:

http://jsfiddle.net/bqyvS/

Markup like this:

<form>
    <div id="color">
        <input type="radio" name="color" id="blue">
        <label for="blue">Blue</label>
        <input type="radio" name="color" id="red">
        <label for="red">Red</label>
        <input type="radio" name="color" id="green">      
        <label for="green">Green</label>
    </div>
    <div id="shape">
        <input type="radio" name="shape" id="square">
        <label for="square">Square</label>
        <input type="radio" name="shape" id="circle">
        <label for="circle">Circle</label>
        <input type="radio" name="shape" id="triangle">
        <label for="triangle">Triangle</label>
    </div>
    <div id="size">
        <input type="radio" name="size" id="small">
        <label for="small">Small</label>
        <input type="radio" name="size" id="medium">
        <label for="mediume">Medium</label>
        <input type="radio" name="size" id="large">      
        <label for="large">Large</label>
    </div>
  </form>
<a id="link" href="#">click me to "submit"</a>
<p id="warning"></p>​

Javascript:

$('#link').on('click', function() {
   if (!$('#color input[type=radio]:checked').length) {
      $('#warning').html("Oops! Please choose a color!"); 
   }
   else if(!$('#shape input[type=radio]:checked').length) {
      $('#warning').text("Oops! Please choose a shape!"); 
   }
   else if(!$('#size input[type=radio]:checked').length) {
     $('#warning').text("Oops! Please choose a size!"); 
   } 
});

This is a simplified version of a larger piece of code. How can I rewrite the conditional more efficiently so that I'm not verbosely checking each input name? (There should only be one "warning" displayed per "submit", even if multiple input name categories aren't checked.) Editing the markup would be okay.

Thanks!

function validationCheck() {
    var isValid = true,
        errorText = "";
    $("form div").each(  //get the divs that hold the radios and loop
    //$("#color, #shape, #size").each( //could do it by ids of the divs also
        function(){
            var div = jQuery(this),  //div reference
                isChecked = div.find('input[type="radio"]:checked').length>0;  //see if we have anything selected
            if (!isChecked) {  //if no selections, show error message
                isValid = false;  //set validation to false
                errorText = "Oops! Please choose a " + div.prop("id") + "!";  //build error message
                return false;  //exit each loop
            }
        }
    );
    $('#warning').text(errorText); //set error message
    return isValid;
}

When applying behavior to similar groups, you should start thinking about classes instead of ids, in this solution, you don't need a separate data-name but I believe it's better to have data separate from html id, but you could use this.id if you prefer

<form>
    <div id="color" class="selection-group" data-name="color">
        <input type="radio" name="color" id="blue">
        <label for="blue">Blue</label>
        <input type="radio" name="color" id="red">
        <label for="red">Red</label>
        <input type="radio" name="color" id="green">      
        <label for="green">Green</label>
    </div>
    <div id="shape" class="selection-group" data-name="square">
        <input type="radio" name="shape" id="square">
        <label for="square">Square</label>
        <input type="radio" name="shape" id="circle">
        <label for="circle">Circle</label>
        <input type="radio" name="shape" id="triangle">
        <label for="triangle">Triangle</label>
    </div>
    <div id="size" class="selection-group" data-name="size">
        <input type="radio" name="size" id="small">
        <label for="small">Small</label>
        <input type="radio" name="size" id="medium">
        <label for="mediume">Medium</label>
        <input type="radio" name="size" id="large">      
        <label for="large">Large</label>
    </div>
  </form>
<a id="link" href="#">click me to "submit"</a>
<p id="warning"></p>​

Javascript:

$('#link').on('click', function() {
   $('.selection-group').each(function() {
      if(!$(this).find('input[type=radio]:checked').length) {
          $('#warning').html("Oops! Please choose a "+ $(this).data('name') +"!"); 
          return false;
      }
   });
});
$('#link').on('click', function(){
  $('#color, #shape, #size').each(function(i, ele){
      if($(this).find('input:checked').length == 0)
        $('#warning').text("Oops! Please choose a " + this.id + "!");
  });
}); 

jsFiddle

You may want to consider generating a warning message in the case a user does not select any inputs or only 1 input.

In this example, a user will recieve a message similar to Oops! Please choose a color, and shape! Oops! Please choose a color, and shape!

$('#link').on('click', function(){
  var msgs = [];

  $('#color, #shape, #size').each(function(i, ele){
    if($(this).find('input:checked').length == 0)
      msgs.push(this.id);
  });

  if(msgs.length > 0)
    $('#warning').text("Oops! Please choose a " + msgs.join(", and "));
}); 

jsFiddle

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