Reputation: 853
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
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
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
Reputation: 62566
There are a few problems there:
getElementsByClassName
you should use the classname without the dot.style
property is for the element (while getElementsByClassName
returns a list of the elements).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