Flutterer
Flutterer

Reputation: 239

How to shorten repetitive validation code

$('#add_product_form').on('submit',function(){
    if ($('#product_date').val() == '') {
        $('#product_date').addClass('border-danger');
    }else{
        $('#product_date').removeClass('border-danger');
    }
    if ($('#product_name').val() == '') {
        $('#product_name').addClass('border-danger');
    }else{
        $('#product_name').removeClass('border-danger');
    }
    if ($('#select_category').val() == '') {
        $('#select_category').addClass('border-danger');
    }else{
        $('#select_category').removeClass('border-danger');
    }
    if ($('#select_brand').val() == '') {
        $('#select_brand').addClass('border-danger');
    }else{
        $('#select_brand').removeClass('border-danger');
    }
    if ($('#product_price').val() == '') {
        $('#product_price').addClass('border-danger');
    }else{
        $('#product_price').removeClass('border-danger');
    }
    if ($('#product_quantity').val() == '') {
        $('#product_quantity').addClass('border-danger');
    }else{
        $('#product_quantity').removeClass('border-danger');
    }
 })

This is one form with many fields. How can we shorten this code? I have tried same code in vanilla Javascript and obviously it contains more lines of code. Is there any better way to write this type of code?

Upvotes: 1

Views: 107

Answers (3)

Jon P
Jon P

Reputation: 19802

Instead of having to maintain a list of fields in your JavaScript, use the required attribute and leverage this in your script. This also will leverage the browsers inbuilt validation. If you don't want to use the inbuilt validation you can use a different attribute as I've done below. If you want to use the normal required attribute, just use that instead of data-custRequired

$("#form").submit(function() {
  var valid = true;
  $(this).find("[data-custRequired]").each(function() {
    var itemValid = true;
    if (this.tagName === "FIELDSET") {
      itemValid = $(this).find(":checked").length > 0;           
    }
    //Otherwise validate normally
    else {
      itemValid = $(this).val() !== ""      
    }
    
    $(this).toggleClass("danger-border", !itemValid );
    if(!itemValid) 
    {
      valid = false;
    }
  });
  console.log("Form Valid = " + valid);
  
  return false;
})
label {
  display: block;
}

.danger-border {
  border: red 1px solid;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="form">
  <label>First Name <input type="input" name="firstName" data-custRequired /></label>
  <label>Last Name <input type="input" name="lastName" data-custRequired /></label>
  <label>Comment <input type="input" name="comment"></label>
  <fieldset data-custRequired>
    <legend>Can we contact you - required</legend>
    <label><input type="radio" name="contact"> Yes </label>
    <label><input type="radio" name="contact">No </label>
    <label><input type="radio" name="contact">Maybe </label>
  </fieldset>
  <input type="submit">
</form>

Vanilla Javascript

Not a whole lot more needed

document.getElementById("form").addEventListener("submit", function(event) {
  var requiredElements = this.querySelectorAll("[data-custRequired]");
  var valid = true;
  for (var i = 0; i < requiredElements.length; i++) {
    var itemValid = true;
    var el = requiredElements[i];
    if (el.tagName === "FIELDSET") {
      itemValid = el.querySelectorAll(":checked").length > 0;
    } else {
      itemValid = el.value !== "";
    }

    //To support IE 10 we don't use the inbuilt toggle
    if (itemValid) {
      el.classList.remove("danger-border");
    } else {
      el.classList.add("danger-border");
      valid = false;
    }
  }

  console.log("Form Valid = " + valid);
  event.preventDefault();
  return false;
})
label {
  display: block;
}

.danger-border {
  border: red 1px solid;
}
<form id="form">
  <label>First Name <input type="input" name="firstName" data-custRequired /></label>
  <label>Last Name <input type="input" name="lastName" data-custRequired /></label>
  <label>Comment <input type="input" name="comment"></label>
  <fieldset data-custRequired>
    <legend>Can we contact you - required</legend>
    <label><input type="radio" name="contact"> Yes </label>
    <label><input type="radio" name="contact">No </label>
    <label><input type="radio" name="contact">Maybe </label>
  </fieldset>
  <input type="submit">
</form>

Upvotes: 0

charlietfl
charlietfl

Reputation: 171690

You can use an each loop.

Adding a common class to the elements would simplify initial selector or use something like $(this).find(':input[required]').each...

$('#add_product_form').on('submit', function() {
  $('#product_date,#product_name,#select_category,#select_brand,#product_price,#product_quantity').each(function() {
      $(this).toggleClass('border-danger', !this.value);
  });
});

Upvotes: 1

Bryan
Bryan

Reputation: 1005

It's best to make a function for repetitive things like this:

function validate($selector) {
    $selector.toggleClass('border-danger', $selector.val() == '')
}

$('#add_product_form').on('submit',function(){
    validate($('#product_date'));
    validate($('#product_name'));
    validate($('#select_category'));
    validate($('#select_brand'));
    validate($('#product_price'));
    validate($('#product_quantity'));
});

Upvotes: 2

Related Questions