kevin_b
kevin_b

Reputation: 853

How to change border color of checkboxes in Javascript

I am learning how to do form validation on various types of elements and want to do this in only Javascript. I have some checkboxes here and a Javascript function that checks if the checkboxes has at least one option selected on form submission. Basically the checkboxes should show up red if no option is selected. But I get the error:

Uncaught TypeError: Cannot set property 'borderColor' of undefined

function validate() {
  var ok = true;
  var yes = document.getElementById("yes").checked
  var no = document.getElementById("no").checked;

  if (!yes && !no) {
    document.getElementsByClassName(".btn-group").style.borderColor = "red";
  }

  return ok;
}
<div data-toggle="buttons" class="btn-group">
  <label class="btn active">
    <input id = "yes" type="checkbox" name="box" value="yes" />
    </i>Yes
  </label>

  <label class="btn active">
    <input id = "no" type="checkbox" name="box" value="no" />No
  </label>
</div>

Upvotes: 1

Views: 6875

Answers (3)

NAMS
NAMS

Reputation: 991

getElementsByClassName() Returns a collection of elements, so you need to iterate over the result to make sure you apply the style change to each element.

Furthermore, you need to use the element.setAttribute() method to change the style like so:

element.setAttribute("style","border-color: red");

Combining those two things should get you the result you want.

Edit: you don't have to use setAttribute() if you don't want to, as Neal pointed out. The important thing to take away is that you need to iterate over your collection.

Edit 2: Looking at your code again, I noticed that when you call document.getElementsByClassName(".btn-group").style.borderColor = "red";, you're not retrieving the check boxes, you're getting a collection of divs of class btn-group, so you're actually attempting to set the border color of the div to be red, not the check boxes. You're also always returning true unconditionally at the end of validate().

If you're only checking these 2 check boxes, you can just simply use the id's to change them:

function validate() {
  var ok = true;
  var yes = document.getElementById("yes").checked
  var no = document.getElementById("no").checked;

  if (!yes && !no) {
    document.getElementById("yes").setAttribute("style","border-color: red");
    document.getElementById("no").setAttribute("style","border-color: red");
    // no checkbox selected, validation should fail and return false
    return !ok;
  } else {
    // checkbox selected, validation should pass and return true
    return ok;
  }
}

Upvotes: 1

Mr. Polywhirl
Mr. Polywhirl

Reputation: 48630

You should add or remove a class to the button group in order to hide show the border. Just add or remove the class when validation changes.

Also, you need to either iterate over all the button group classes or choose one.

Note: I used the class methods from You Might Not Need jQuery.

function validate() {
  var btnGroups = document.getElementsByClassName("btn-group");

  for (var i = 0; i < btnGroups.length; i++) {
    var btnGroup = btnGroups[i];
    var yes = document.getElementById("yes")['checked'] == true;
    var no = document.getElementById("no")['checked'] == true;

    if (!yes && !no) {
      if (!hasClass(btnGroup, 'invalid')) addClass(btnGroup, 'invalid');
      return false;
    } else {
      if (hasClass(btnGroup, 'invalid')) removeClass(btnGroup, 'invalid');
    }
  }

  return true;
}

function hasClass(el, className) {
  if (el.classList) return el.classList.contains(className);
  else return new RegExp('(^| )' + className + '( |$)', 'gi').test(el.className);
}

function addClass(el, className) {
  if (el.classList) el.classList.add(className);
  else el.className += ' ' + className;
}

function removeClass(el, className) {
  if (el.classList) el.classList.remove(className);
  else el.className = el.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
}
.btn-group.invalid {
  border : thin solid red;
}
<div data-toggle="buttons" class="btn-group">
  <label class="btn active">
    <input type="checkbox" id="yes" name="box" value="yes" onchange="validate()" />Yes
  </label>

  <label class="btn active">
    <input type="checkbox" id="no" name="box" value="no" onchange="validate()" />No
  </label>
</div>

Upvotes: 0

Dekel
Dekel

Reputation: 62566

There are a few problems there:

  1. If you use getElementsByClassName you should use the classname without the dot.
  2. The style property is for the element (while getElementsByClassName returns a list of the elements).
  3. If you only set the color of the border (and not the style and the width) there will be no border.

Here is the correction:

function validate() {
  var ok = true;
  var yes = document.getElementById("yes").checked
  var no = document.getElementById("no").checked;

  if (!yes && !no) {
    ok = false;
    document.getElementsByClassName("btn-group")[0].style.border = '1px solid red';
  } else {
    document.getElementsByClassName("btn-group")[0].style.border = '';
  }
  return ok;
}
<div data-toggle="buttons" class="btn-group">
  <label class="btn active">
    <input id = "yes" type="checkbox" name="box" value="yes" />
    Yes
  </label>

  <label class="btn active">
    <input id = "no" type="checkbox" name="box" value="no" />No
  </label>
</div>

<button onclick="validate()">Validate</button>

Upvotes: 4

Related Questions