2

I would like to reset the form after checkboxes in the first fieldset are deselected after initial selection.

How can one accomplish this using vanilla JavaScript?

<form>
<fieldset>
<label><input type="checkbox" name="foo">Apples</label>
<label><input type="checkbox" name="foo">Oranges</label>
</fieldset>

<fieldset>
<label><input type="radio" name="bar">Red</label>
<label><input type="radio" name="bar">Blue</label>
</fieldset>
</form>
Tzar
  • 5,132
  • 4
  • 23
  • 57

4 Answers4

3

You can add a click event handler to the each of the checkboxes and check if the current checkbox is checked. If not, check if any of them have been checked before and if so, use form.reset() to reset the form.

const checkboxes = document.querySelectorAll("input[type=checkbox]");
const form = document.querySelector("form");
var checkedOne = false;

Array.prototype.slice.call(checkboxes).forEach(function(checkbox) {
 checkbox.addEventListener("click", function(e) {
  if (this.checked) {
   checkedOne = true;
  } else {
   if (checkedOne && !document.querySelectorAll("input[type=checkbox]:checked").length) {
    form.reset();
   }
  }
 });
});
<form>
<fieldset>
<label><input type="checkbox" name="foo">Apples</label>
<label><input type="checkbox" name="foo">Oranges</label>
</fieldset>

<fieldset>
<label><input type="radio" name="bar">Red</label>
<label><input type="radio" name="bar">Blue</label>
</fieldset>
</form>
Tzar
  • 5,132
  • 4
  • 23
  • 57
Unmitigated
  • 76,500
  • 11
  • 62
  • 80
  • 1
    `.forEach()` isn't supported in all browsers on node lists, so they should be converted to Arrays first: `Array.prototype.slice.call(checkboxes).forEach()`. – Scott Marcus Aug 17 '18 at 20:23
0

Use the form.reset method:

let checkBoxes = document.querySelectorAll("input[type=checkbox]");

for (let checkbox of checkBoxes) {
   checkbox.addEventListener('change', change)
}


function change() {
    if(!checkBoxes[0].checked && !checkBoxes[1].checked){
       document.getElementById('formID').reset();
    }
}
<form id="formID">
<fieldset>
<label><input type="checkbox" name="foo">Apples</label>
<label><input type="checkbox" name="foo">Oranges</label>
</fieldset>

<fieldset>
<label><input type="radio" name="bar">Red</label>
<label><input type="radio" name="bar">Blue</label>
</fieldset>
</form>
Willem van der Veen
  • 33,665
  • 16
  • 190
  • 155
  • 3
    Inline HTML event handlers (`onchange`) should not be used. `.addEventListener()` should be. Also, just call the `.reset()` method of the `form` instead of manually resetting each form element. – Scott Marcus Aug 17 '18 at 20:22
  • 1
    FYI: `.getElementsByName()` returns a live node list and is very inefficient. Unless you are working with dynamically created/destroyed elements, use `.querySelectorAll()` to get a static node list. – Scott Marcus Aug 17 '18 at 20:31
  • @ScottMarcus Updated the answer now. Is it better this now. Also why should we never use inline event handlers? – Willem van der Veen Aug 17 '18 at 22:12
  • Read **[this](https://stackoverflow.com/questions/43459890/javascript-function-doesnt-work-when-link-is-clicked/43459991#43459991)** for why you shouldn't use inline handlers. And, you are still using `.getElementsByName()`, so no, it's not better now. – Scott Marcus Aug 17 '18 at 23:54
  • @ScottMarcus, nice post about inline event handlers thanks! I also removed the getElementsByName selector. But what is the reason for not using that API? – Willem van der Veen Aug 18 '18 at 08:40
  • See my comment to @Charles Loder below about `.getElementsByName()`. – Scott Marcus Aug 18 '18 at 12:17
  • 1
    No, it's less. A live node list must re-scan the DOM every single time the variable is accessed so that it can return the most up-to-date collection of matching nodes. That is only needed when nodes are being dynamically added or removed. Since that is generally not the case, live node lists can add a huge performance penalty. `.querySelector()` and `.querySelectorAll()` should be the primary ways of getting DOM references and they return static node lists. – Scott Marcus Aug 18 '18 at 12:21
0

Another way using an eventListener

var form = document.querySelector("form");
var fieldset1 = document.getElementById("fieldset1");
var fieldset2 = document.getElementById("fieldset2");
var box1 = fieldset1.elements[0];
var box2 = fieldset1.elements[1];
form.addEventListener('click', function(){
 if( !box1.checked &&  !box2.checked) {
    let radio = document.getElementsByName('bar');
    radio[0].checked = false;
    radio[1].checked = false;
  }
})
<form>
<fieldset id="fieldset1">
<label><input type="checkbox" name="foo">Apples</label>
<label><input type="checkbox" name="foo">Oranges</label>
</fieldset>

<fieldset id="fieldset2">
<label><input type="radio" name="bar">Red</label>
<label><input type="radio" name="bar">Blue</label>
</fieldset>
</form>
  • 2
    Just call the `.reset()` method of the `form` instead of resetting each form element. – Scott Marcus Aug 17 '18 at 20:24
  • FYI: `.getElementsByName()` returns a live node list and is very inefficient. Unless you are working with dynamically created/destroyed elements, use `.querySelectorAll()` to get a static node list. – Scott Marcus Aug 17 '18 at 20:29
-2

Assuming there can be more checkboxes in the top fieldset and many radio button in the others ,you can try this:-

 let masterCheckboxes = document.querySelectorAll("#master input");
 
  masterCheckboxes.forEach(function(ele){
  ele.addEventListener("change", function(){
    var allUnchecked = true;
      masterCheckboxes.forEach(function(ele){
        if(ele.checked)
          allUnchecked = false;

      })
      if(allUnchecked){
        document.querySelectorAll('.other input').forEach(function(ele){
          ele.checked = false;
        })
      }
 });
 
})
 
 
<form>
  <fieldset id="master">
  <label><input type="checkbox" name="foo">Apples</label>
  <label><input type="checkbox" name="foo">Oranges</label>
  </fieldset>

  <fieldset class="other">
  <label><input type="radio" name="bar">Red</label>
  <label><input type="radio" name="bar">Blue</label>
  </fieldset>
</form>
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
Atul
  • 420
  • 2
  • 10