Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

Łukasz Czuliński
Łukasz Czuliński
8,646 Points

Trying to disable submit button if no checkboxes are checked.

This is my most recent attempt. The console quickly flashes up an Uncaught type error. Undefined is not a function when I try to call submitToggle() but pressing submit.

Here is my dubious Javascript:

var $submit = $('#submit');

function submitToggle(){   
    var $checkboxes = new Array();
    $checkboxes = document.getElementsByName('ops[]');
    for(var i = 0; i<=4; i++){
        var $count = 0;
        if ($checkboxes[i].attr('checked')) {
            $count = $count + 1;  
        }
        if ($count < 1) {
            $submit.prop('disabled', true);
            alert("You need to select a box. Or two. Or three.");
        } else{
            $submit.prop('disabled', false);
        }
    }
}

$submit.click(function(){
   $(this).submitToggle(); 
});

I've tried a bunch of things, including prop() on the checkboxes as well. I'm pretty lost.

And my html form:

     <form method="get" action="process.php">
    <table>
      <tr>
        <th><label for="options">Options:</label></th>
          <td>
            <p>Test1</p><input type="checkbox" class="checkbox" name="ops[]" value="Test1">
            <p>Test1</p><input type="checkbox" class="checkbox" name="ops[]" value="Test2">
            <p>Test1</p><input type="checkbox" class="checkbox" name="ops[]" value="Test3">
            <p>Test1</p><input type="checkbox" class="checkbox" name="ops[]" value="Test4">
          </td>
      </tr>
    </table>
    <table>
      <tr>
        <th><label for="description">Notes</label></th>
        <td><input type="text" id="description" name="description"></td>
        <td><button type="submit" id="submit" name="submit" value="Submit"></td>
      </tr>
      </table>
</form>

4 Answers

Erik Nemesis
Erik Nemesis
13,356 Points
$checkboxes = document.getElementsByName('ops[]');

This returns an array of html nodes whose name is "ops", not jQuery objects, so they don't have the method "attr" on them. If you want to get jQuery objects, use the selector $('[name=ops[]]').

var $count = 0;

Don't know what this $count is for but 1) If this is not a jQuery object, don't precede the var name with $, this is confusing; 2) You put this inside the for, so for each iteration it will be resetted to 0. Is this really what you want (I guess not).

$submit.prop('disabled', true)

You should use "attr" here, and be careful that to disable the "disabled state", you will need to remove the attribute, not simply set it to false (using removeAttr)

if ($count < 1)

Hope this helps.

Łukasz Czuliński
Łukasz Czuliński
8,646 Points

Yeah, that $count is habit from learning PHP right now. And yes, putting it inside the for was a mistake.

Thanks for pointing out re: jQuery objects on the getElementsByName method. I never would have thought of that.

All that said, I still couldn't get it to work so I spent some more time on it and came up with some much cleaner code.

It's working almost perfectly except for one hitch. When any number of boxes are checked, the form submits perfectly. When no box is checked, the form correctly alerts the user and stays on the same page. However, I can't figure out how to re-enable submit without refreshing the page when no checkboxes were checked.

var $submit = $('#submit');
var count = 0;

$submit.click(function(){
    $('input[type=checkbox]').each(function(){
    if (this.checked === true) {
        count=count + 1;
    }
    console.log(count); //simply here to make sure it's working
    });
    if (count === 0) {
        $submit.prop('disabled', true);
        alert("Please make sure at least one box has been selected.");
    }
});
$submit.removeAttr('disabled'); //tried multiple ways to re-enable submit, this is just the most recent one
Erik Nemesis
Erik Nemesis
13,356 Points

Well you try to call a METHOD called submitToggle when what you have is a FUNCTION. Plus, you are invoking a method on the jQuery function scope which is not what you declared.

Knowing that, you have two solutions:

  • Either you declare your function inside the jQuery function scope, like this:

$.fn.submitToggle = function(){ ... }

  • Or you don't wanna and simply use the function you declared, so instead of $(this).submitToggle, you would run simply "submitToggle()" inside the clickHndler
Łukasz Czuliński
Łukasz Czuliński
8,646 Points

Thank you. Makes sense. Do you see any issues in the rest of my JS code? I have tried running submitToggle() in the click handler but it's still proceeding to the next page without any checkboxes checked.

Erik Nemesis
Erik Nemesis
13,356 Points

It's because you keep a reference to the counter as a GLOBAL VARIABLE. That way, it means that it would not be initialized everytime.

Put it inside your click handler and you're done.

Łukasz Czuliński
Łukasz Czuliński
8,646 Points

For some reason that still didn't change the disabled attribute. I'm sure it was some error in the way I was trying to enable the submit button again.

The good thing is that while messing around some more I made a much cleaner, simpler code that finally does exactly what I want it to:

var $submit = $('#submit');
$checkbox = $('input[type=checkbox]');

$submit.prop('disabled', true);

$checkbox.on('click', function(){
    if ($("input:checkbox:checked").length > 0) {
        $submit.removeAttr('disabled');
    }else{
        $submit.prop('disabled', true);
    }
});

Thanks so much for all the help. I definitely plugged a few holes in my weak Javascript.