23

I have a form containing various fields.

See jsFiddle demo.

My aim is to enable the submit button only when the user has filled in all fields.

So far, I'm able to force the title field to have content before submit button is enabled. How do I make it so that all other fields need to be filled too before submit button is enabled.

    jQuery("input[type='text']").on("keyup", function () {
        if (jQuery(this).val() != "" ) {
            if (jQuery("#titlenewtide").val() != '')
            {
                jQuery("#subnewtide").removeAttr("disabled");
            }
        } else {
            jQuery("#subnewtide").attr("disabled", "disabled");
        }
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="#" method="post" id="new_tide">
        Title: <input id="titlenewtide" type="text" name="title" required> <br>
        Description: <textarea name="description" id="description"></textarea> <br>
        Tag:  <input id="newtag" type="text" name="newtag" required> <br>
        Category: <input type="radio" name="category" value="19" required> Animation
        <button type="submit" value="Submit" name="subnewtide" id="subnewtide" disabled="disabled">Submit</button> 
    </form>

Note that I am loading the JavaScripts in my footer.

Dwhitz
  • 1,250
  • 7
  • 26
  • 38
Henrik Petterson
  • 6,862
  • 20
  • 71
  • 155

13 Answers13

16
  • Make the changes take effect after changing inputs values:

On each input change, test the values of other inputs and checked state of radio, if all inputs has been entered it will make the submit button enabled:

var validateInputs = function validateInputs(inputs) {
  var validForm = true;
  inputs.each(function(index) {
    var input = $(this);
    if (!input.val() || (input.type === "radio" && !input.is(':checked'))) {
      $("#subnewtide").attr("disabled", "disabled");
      validForm = false;
    }
  });
  return validForm;
}

inputs.change(function() {
  if (validateInputs(inputs)) {
    $("#subnewtide").removeAttr("disabled");
  }
});

Demo:

var inputs = $("form#myForm input, form#myForm textarea");

var validateInputs = function validateInputs(inputs) {
  var validForm = true;
  inputs.each(function(index) {
    var input = $(this);
    if (!input.val() || (input.type === "radio" && !input.is(':checked'))) {
      $("#subnewtide").attr("disabled", "disabled");
      validForm = false;
    }
  });
  return validForm;
}


inputs.change(function() {
  if (validateInputs(inputs)) {
    $("#subnewtide").removeAttr("disabled");
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="#" method="post" id="myForm">

  Title:
  <input id="titlenewtide" type="text" name="title" required>
  <br>Description:
  <textarea name="description" id="description"></textarea>
  <br>Tag:
  <input id="newtag" type="text" name="newtag" required>
  <br>Category:
  <input type="radio" name="category" value="19" required>Animation
  <button type="submit" value="Submit" name="subnewtide" id="subnewtide" disabled="disabled">Submit</button>

</form>

Also it uses the form id="myForm", so you can use it to validate only specific forms in your pages.

Note: This is tested and working on Chrome, Firefox and IE.


EDIT:

  • Make the changes take effect when we type in the inputs:

In the previous code we are using onchange event handler to call the function so it's only called when we click outside a given input (after change).

To perform the call automatically when the user enters a character in a field (the last one) we need to use the onkeyup event so we don't need to click outside of it.

This is the changed code you need :

    var inputs = $("form#myForm input, form#myForm textarea");

    var validateInputs = function validateInputs(inputs) {
      var validForm = true;
      inputs.each(function(index) {
        var input = $(this);
        if (!input.val() || (input.type === "radio" && !input.is(':checked'))) {
          $("#subnewtide").attr("disabled", "disabled");
          validForm = false;
        }
      });
      return validForm;
    }


    inputs.each(function() {
      var input = $(this);
      if (input.type === "radio") {
        input.change(function() {
          if (validateInputs(inputs)) {
            $("#subnewtide").removeAttr("disabled");
          }
        });
      } else {
        input.keyup(function() {
          if (validateInputs(inputs)) {
            $("#subnewtide").removeAttr("disabled");
          }
        });
      }
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="#" method="post" id="myForm">

  Title:
  <input id="titlenewtide" type="text" name="title" required>
  <br>Description:
  <textarea name="description" id="description"></textarea>
  <br>Tag:
  <input id="newtag" type="text" name="newtag" required>
  <br>Category:
  <input type="radio" name="category" value="19" required>Animation
  <button type="submit" value="Submit" name="subnewtide" id="subnewtide" disabled="disabled">Submit</button>

</form>
cнŝdk
  • 31,391
  • 7
  • 56
  • 78
  • When clicking inside an input, and then clicking outside of it, it will enable the submit button...? – Henrik Petterson Aug 01 '15 at 14:36
  • 1
    no need to iterate `inputs` using `each` to apply change handler ... `inputs.change()` is same thing – charlietfl Aug 01 '15 at 14:36
  • @HenrikPetterson yes but only if all the inputs was entered/checked. – cнŝdk Aug 01 '15 at 14:40
  • No, I just tested this on latest version of FF and was able to enable the submit button even when there are no content inside the fields. – Henrik Petterson Aug 01 '15 at 14:41
  • @HenrikPetterson I just edited it, and I tested it with FF and IE and it works perfectly – cнŝdk Aug 01 '15 at 15:45
  • Thank you for the update. I can't seem to make this work correctly. Note that I am loading the JS code in my footer. Is that the cause of the problem? – Henrik Petterson Aug 03 '15 at 21:15
  • If you enter something in every field the button enables, then if you remove content from any field it remains enabled. OP didnt specify this behaviour, but its pretty common. – Jamiec Aug 04 '15 at 15:32
  • @Jamiec Thank you for pointing it out, I fixed it, we only need to reset the button to disabled by adding this line `$("#subnewtide").attr("disabled", "disabled");` before returning `false`. – cнŝdk Aug 05 '15 at 00:29
  • @HenrikPetterson I don't think so but it may be that, try to includ ethe script in the head of the page and test it, because anyway the function call should be atached to the change event of the inputs once the page is loaded. – cнŝdk Aug 05 '15 at 00:32
  • @chsdk I ran final tests with this code and everything is working beside one major issue. In FF and likely all browsers, the submit button is enable only once the user clicks outside of the textarea. To test this, click the radio button first, then fill all the input/textarea... one you are at the last one, the submit button doesn't get enabled until you click outside of it, which is highly confusing for the user. Do you have a fix for this? Thanks for the code regardless, I learned a lot! – Henrik Petterson Aug 07 '15 at 16:37
  • @HenrikPetterson Yes of course we can do it we should just use the `onkeyup` event instead of the `onchange` event to perform the change instantly when the users enters some characters, take a look at my EDIT you will find what you need. – cнŝdk Aug 07 '15 at 17:44
10

Use this code below. On each input, it will check all the form fields by using this function validate().

jQuery("input[type='text'], textarea").on("input", function () {
    var isValid = validate();
    if (isValid) {
      jQuery("#subnewtide").removeAttr("disabled");
    } else {
        jQuery("#subnewtide").attr("disabled", "disabled");
    }
});


function validate() {
  var isValid = true;
  $('input, textarea').each(function() {
    if ($(this).val() === '')
        isValid = false;
  });
  return isValid;
}

Fiddle

Update

To make it validate if the form has id="new_tide" and fix about the radio button.

$("input[type='text'], textarea").on("change input", function() {
  validate($(this));
});

$("input:radio[name='category']").on("change", function() {
    validate($(this));
});

function validate(self) {
  if (self.parents("form:first").attr("id") == "new_tide") {
    var isValid = true;
    $('input[type="text"], textarea').each(function() {
      if ($(this).val() === '')
        isValid = false;
    });

    if (!$("input:radio[name='category']").is(':checked'))
      isValid = false;

    if (isValid) {
      $("#subnewtide").removeAttr("disabled");
    } else {
      $("#subnewtide").attr("disabled", "disabled");
    }
  }
}

Fiddle

Robin Carlo Catacutan
  • 13,249
  • 11
  • 52
  • 85
6

Here's how you can do it:

$(document).ready(function () {
    var $inputs = $("#new_tide input:not([type=hidden]), #new_tide textarea");

    $inputs.on("input change", function () {
        valid = true;
        $inputs.each(function () {
            valid *= this.type == "radio" ? this.checked : this.value != "";
            return valid;
        });    
        $("#subnewtide").prop("disabled", !valid);
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<form action="#" method="post" id="new_tide">
    Title: <input id="titlenewtide" type="text" name="title" required> <br>
    Description: <textarea name="description" id="description"></textarea> <br>
    Tag:  <input id="newtag" type="text" name="newtag" required> <br>
    Category: <input type="radio" name="category" value="19" required> Animation
    Hidden: <input type="hidden">
    <button type="submit" value="Submit" name="subnewtide" id="subnewtide" disabled="disabled">Submit</button> 
</form>
Johan Karlsson
  • 6,419
  • 1
  • 19
  • 28
5

Try utilizing .siblings() , .map() to compile values of form elements , Array.prototype.every() to return Boolean representation of input , textarea values , set disabled property of form input[type=submit] element

$("form *[required]").on("input change", function(e) {
  $(this).siblings("[type=submit]").prop("disabled"
  , !$(this).siblings(":not([type=submit])").add(this).map(function(_, el) {
    return el.type === "radio" ? el.checked : el.value
   }).get().every(Boolean)
  );
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<form action="#" method="post" id="new_tide">
    Title: <input id="titlenewtide" type="text" name="title" required> <br>
    Description: <textarea name="description" id="description" required></textarea> <br>
    Tag:  <input id="newtag" type="text" name="newtag" required> <br>
    Category: <input type="radio" name="category" value="19" required> Animation
    <button type="submit" value="Submit" name="subnewtide" id="subnewtide" disabled="disabled">Submit</button> 
</form>
guest271314
  • 1
  • 15
  • 104
  • 177
3

By far the easiest, would be to rely on the HTML5 validation you're already using.

You'd have to add required to all form controls if you want to require all of them, and that can easily be done by using jQuery's :input selector and setting the property, like so

$(':input:not(#subnewtide)').prop('required', true)

We'll exclude the submit button, as that doesn't have to be required, obviously, not that it would matter in this case.

Then we'll listen for the input event, which covers all sorts of inputs, like typing, pasting etc, and the change event as well to cover the radio button.

Using form.checkValidity() tells us if the form is valid, and returns a boolean, so we could use it directly to set the disabled property of the submit button.

All together it looks like this, and that's all you need, a few lines of really simple code

$(':input:not(#subnewtide)').prop('required', true).on('input change', function() {
    $('#subnewtide').prop( 'disabled', !this.form.checkValidity() );
});

FIDDLE

If you have to support old browsers that don't have HTML5 validation, you can use the H5F polyfill

adeneo
  • 312,895
  • 29
  • 395
  • 388
2

My solution is base on standard JavaScript.

HTML form

<form action="#" method="post" id="new_tide" name="form1">
    Title: <input onkeyup="myBtnActivator(1)" id="titlenewtide" name="title" type="text" required> <br>
    Description: <textarea onkeyup="myBtnActivator(2)" id="description" name="description"></textarea> <br>
    Tag: <input id="newtag" onkeyup="myBtnActivator(3)" name="newtag" type="text" required> <br>
    Category: <input name="category" onchange="myBtnActivator(4)" type="radio" value="19" required> Animation
    <button id="subnewtide" name="subnewtide" type="submit" value="Submit">Submit</button>
</form>

JavaScript

<script>
    document.getElementById("subnewtide").disabled = true;
    var input1 = false;
    var input2 = false;
    var input3 = false;
    var input4 = false;

    function myBtnActivator(i) {
        switch (i) {
            case 1:
                input1 = true;
                if (document.form1.title.value == "")
                    input1 = false;
                break;
            case 2:
                input2 = true;
                if (document.form1.description.value == "")
                    input2 = false;
                break;
            case 3:
                input3 = true;
                if (document.form1.newtag.value == "")
                    input3 = false;
                break;
            case 4:
                input4 = true;
                if (document.form1.subnewtide.value == "")
                    input4 = false;
                break;
        }
        trigger();
    }

    function trigger() {
        if (input1 == true && input2 == true && input3 == true && input4 == true) {
            document.getElementById("subnewtide").disabled = false;
        } else {
            document.getElementById("subnewtide").disabled = true;
        }
    }
</script>
Maytham Fahmi
  • 31,138
  • 14
  • 118
  • 137
1

Why don't you use jquery validate . It's a good plugin .

The logic works like, any change in the form it will check the form is valid or not. And also using the errorplacement function it will disable the default error message also.

$().ready(function() {
    // validate signup form on keyup and submit
    $("#contactForm").validate({
        rules: {
            title: "required",
            description: {
                required: true
            },
            newtag: {
                required: true
            },
            category: {
                required: true
            }
        },
        errorPlacement: function(error, element) {
            return true;
        },
        submitHandler: function() {


        }
    });


    $('#contactForm').change(function() {
        if ($("#contactForm").valid()) {
            $("#subnewtide").removeAttr("disabled");
        }
    });

});

Fiddle

harilalkm
  • 456
  • 1
  • 4
  • 15
1

There's actually a pretty easy approach. I'm using native JavaScript, but I think it is applicable in jQuery as well:

var form = document.getElementById("new_tide");
form.onchange = function onChange() {
    var enable = true;
    var inputs = form.getElementsByTagName("input");
    var textareas = form.getElementsByTagName("textarea");

    for (var i in inputs) {
        enable = enable && inputs[i].value != "";
    }

    for (var i in textareas) {
        enable = enable && textareas[i].value != "";
    }

    enable = enable && textarea.value != "";
    document.getElementById("subnewtide").disabled = !enable;
}

The change event on form is always called, when any input or textarea element was changed (click in element, type, click somewhere else or lose focus).

Edit:
Regarding hidden fields, you can exclude them by surrounding the enable calculation with an if-condition:

if (!inputs[i].hidden) {
    enable = enable && inputs[i].value != "";
}

Note:
This will work in any browser (even Internet Explorer 5.5). Check on MDN:

for ..in Loop
element.getElementsByTagName()
document.getElementById()

G_hi3
  • 588
  • 5
  • 22
1

Thought I might chip in. Assuming as little as possible.

jQuery("input, textarea").on("keyup click", function () { // going vanilla after easy-mode attach
    var sub = document.getElementById('subnewtide');
    if (require_all(find_form(this))) {
        sub.removeAttribute('disabled');
        sub.disabled = false;
    } else {
        sub.setAttribute('disabled', 'disabled');
        sub.disabled = true;
    }
});

function concat(a, b) { // concating Array-likes produces Array
    var slice = [].slice; // not assuming Array.prototype access
    return [].concat.call(
        slice.call(a, 0),
        slice.call(b, 0)
    );
}

function find_form(e) { // shim input.form
    if (e) do {
        if (e.tagName === 'FORM') return e;
    } while (e = e.parentNode);
    return null;
}

function require_all(form, dontIgnoreHidden) { // looks at textareas & inputs (excluding buttons)
    var inp = concat(form.getElementsByTagName('input'), form.getElementsByTagName('textarea')),
        rad = {}, // not assuming Object.create
        i, j,
        has = {}.hasOwnProperty; // not assuming Object.prototype access
    for (i = 0; i < inp.length; ++i) {
        switch ((inp[i].type || '').toLowerCase()) {
            default: // treat unknown like texts
            case 'text':
                if (!inp[i].value) return false; break;
            case 'checkbox':
                if (!inp[i].checked) return false; break;
            case 'radio':
                j = inp[i].getAttribute('name');
                if (!rad[j]) rad[j] = inp[i].checked;
                break;
            case 'hidden':
                if (dontIgnoreHidden && !inp[i].value) return false; break;
            case 'button':
            case 'submit':
                break;
        }
    }
    for (j in rad) if (!has || has.call(rad, j)) // not assuming hasOwnProperty
        if (!rad[j]) return false;
    return true;
}
Paul S.
  • 64,864
  • 9
  • 122
  • 138
1

Here is a quick way to accomplish that. It involves attaching a change event listener to :radio and :checkbox elements and an input event listener to other elements. These can both use a common predefined handler that will count the number of unfilled element each time each of these events fires on the appropriate element.

function checkForm() {
    //define and initialize variables
    var unfilled = 0,
        form = $(this.form);

    //disable submit button if enabled
    $(':submit', form).prop('disabled', true);

    //count number of unfilled elements
    $(':input', form).each(function() {
        if( $(this).is(':radio,:checkbox') ) {
            $('input[name=' + this.name + ']:checked').length || unfilled++;
        } else {
            $('[name=' + this.name + ']').val() || unfilled++;
        }
    });
  
    //enable submit button if no unfilled element is found
    unfilled || $(':submit', form).prop('disabled', false);
}

//set up event listeners to fire above handler
$(':text,textarea,select').on('input', checkForm);
$(':radio,:checkbox').on('change', checkForm);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<form action="#" method="post" id="new_tide">
    Title: <input id="titlenewtide" type="text" name="title" required> <br>
    Description: <textarea name="description" id="description"></textarea> <br>
    Tag:  <input id="newtag" type="text" name="newtag" required> <br>
    Category: <input type="radio" name="category" value="19" required> Animation
    <button type="submit" value="Submit" name="subnewtide" id="subnewtide" disabled="disabled">Submit</button> 
</form>
PeterKA
  • 24,158
  • 5
  • 26
  • 48
1

    var inputs = $("form#myForm input, form#myForm textarea");

    var validateInputs = function validateInputs(inputs) {
      var validForm = true;
      inputs.each(function(index) {
        var input = $(this);
        if (!input.val() || (input.type === "radio" && !input.is(':checked'))) {
          $("#subnewtide").attr("disabled", "disabled");
          validForm = false;
        }
      });
      return validForm;
    }


    inputs.each(function() {
      var input = $(this);
      if (input.type === "radio") {
        input.change(function() {
          if (validateInputs(inputs)) {
            $("#subnewtide").removeAttr("disabled");
          }
        });
      } else {
        input.keyup(function() {
          if (validateInputs(inputs)) {
            $("#subnewtide").removeAttr("disabled");
          }
        });
      }
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="#" method="post" id="myForm">

  Title:
  <input id="titlenewtide" type="text" name="title" required>
  <br>Description:
  <textarea name="description" id="description"></textarea>
  <br>Tag:
  <input id="newtag" type="text" name="newtag" required>
  <br>Category:
  <input type="radio" name="category" value="19" required>Animation
  <button type="submit" value="Submit" name="subnewtide" id="subnewtide" disabled="disabled">Submit</button>

</form>
Ravi Kharinta
  • 69
  • 1
  • 8
0
Use this html<br>
HTML:
<br>
<pre>
<form action="#" method="post" id="">
        Title: ##<input id="titlenewtide" type="text" name="title" required> 
        Description: <textarea name="description" id="description"></textarea>
        Tag:  <input id="newtag" type="text" name="newtag" required> 
        Category: <input type="checkbox" onclick="validate()" name="category" id="cate"value="19" required > Animation
        <button type="submit" value="Submit" name="subnewtide" id="subnewtide" disabled="disabled">Submit</button>

</form>
</pre>
validation code:<br>
//on each key up function intiate the function validate
<pre>
    jQuery("input[type='text']").on("keyup", function () {
        validate();
    });
    jQuery("#description").on("keyup", function () {
        validate();
    });

    function validate(){
     jQuery("input[type='text']").each(function(){

        if (jQuery(this).val() != "" )
        {
            if((jQuery("#description").val() !="") && (jQuery("#cate").is(':checked')))
            {

                jQuery("#subnewtide").removeAttr("disabled"); 
            }
            else {
                jQuery("#subnewtide").attr("disabled", "disabled");
            }
        } 
    });
    }
    </pre>
    you can find the fiddle in : https://jsfiddle.net/s8uv2gkp/
0

Maytham Fahmi's relatively easy solution can be made even easier by passing this.name.

<form action="#" method="post" id="new_tide" name="form1">
    <input onkeyup="myBtnActivator(this.name)" name="title" type="text" required> <br>
    <textarea onkeyup="myBtnActivator(this.name)" name="description"></textarea> <br>
    <input id="newtag" onkeyup="myBtnActivator(this.name)" name="newtag" type="text" required> <br>
    <input name="category" onchange="myBtnActivator(this.name)" type="radio" value="19" required> Animation
    <button id="subnewtide" name="subnewtide" type="submit" value="Submit">Submit</button>
</form>

this refers to the DOM object that called the function. So the switch can just directly take the name, or the value, or anything else you can pass with DOM.

myBtnActivator(n)
{
    switch(n)
    {
        case "title":
            break;
        case "description":
            break;
        case "newtag":
            break;
        case "category":
            break;
    }
}
Amaroq
  • 91
  • 1
  • 5