Columbus
Columbus

Reputation: 89

Enable/disable all inputs and checkboxes with any checked checkbox

I have a form with many text-input-fields and checkboxes. Whenever a checkbox is checked, all text-input fields and all other checkboxes (exept the one that was checked) should be disabled. After unchecking this checkbox, all disabled fields should be enabled again. This works with the following code (shown are only the first 3 lines):

<form id="myForm">

    Checkbox 1: <input type="checkbox" name="checkbox1" id="checkboxOne" onclick="enableDisableAll();" />
    <input type="text" id="id1" name="name1" /><br>

    Checkbox 2: <input type="checkbox" name="checkbox2" id="checkboxTwo" onclick="enableDisableAll();" />
    <input type="text" id="id2" name="name2" /><br>

    Checkbox 3: <input type="checkbox" name="checkbox3" id="checkboxThree" onclick="enableDisableAll();" />
    <input type="text" id="id3" name="name3" /><br>

</form>


function enableDisableAll() {

    cb1 = document.getElementById('checkboxOne').checked;
    cb2 = document.getElementById('checkboxTwo').checked;
    cb3 = document.getElementById('checkboxThree').checked;


    document.getElementById('checkboxOne').disabled = (cb2 || cb3);
    document.getElementById('id1').disabled = (cb1 || cb2 || cb3);

    document.getElementById('checkboxTwo').disabled = (cb1 || cb3);
    document.getElementById('id2').disabled = (cb1 || cb2 || cb3);

    document.getElementById('checkboxThree').disabled = (cb1 || cb2);
    document.getElementById('id3').disabled = (cb1 || cb2 || cb3);

}

Since the code becomes confusing with many checkboxes (cb1 || cb2 || cb3 || ....... cb(n)), I wonder if there would be a more elegant possibility to do this, e.g.:

function enableDisableAll() {

cb1 = document.getElementById('checkboxOne').checked;
cb2 = document.getElementById('checkboxTwo').checked;
cb3 = document.getElementById('checkboxThree').checked;

var cb_array = [];

cb_array.push("cb1");
cb_array.push("cb2");

var cb_array_imploded = cb_array.join(" || ");

document.getElementById('id1').disabled = (cb_array_imploded);

Unfortunately, this does not work.

Does anyone have a simple solution for my problem?

Upvotes: 1

Views: 8867

Answers (3)

Dinesh undefined
Dinesh undefined

Reputation: 5546

select all the form elements and loop through and check for id same as clicked element id.if so don't disabled it.

function enableDisableAll(e) {
        var own = e;
        var form = document.getElementById("myForm");
        var elements = form.elements;

    for (var i = 0 ; i < elements.length ; i++) {
          if(own !== elements[i] ){
          
            if(own.checked == true){
              
              elements[i].disabled = true;  
             
            }else{
            
              elements[i].disabled = false;  
            }
          
           }

     }
    
}

function clearAll(){
 document.getElementById("myForm").reset();
}
<form id="myForm">

    Checkbox 1: <input type="checkbox" name="checkbox1" id="checkboxOne" onclick="enableDisableAll(this);" />
    <input type="text" id="id1" name="name1" /><br>

    Checkbox 2: <input type="checkbox" name="checkbox2" id="checkboxTwo" onclick="enableDisableAll(this);" />
    <input type="text" id="id2" name="name2" /><br>

    Checkbox 3: <input type="checkbox" name="checkbox3" id="checkboxThree" onclick="enableDisableAll(this);" />
    <input type="text" id="id3" name="name3" /><br>
 
   

</form>

<input class="field button2" type="button" value="Clear form" size="10" onclick="clearAll(this);">

Update : To clear all the form fields

document.getElementById("myForm").reset();

Upvotes: 1

David Thomas
David Thomas

Reputation: 253318

One possible approach is the following; though note that I amended your HTML, wrapping the <input type="checkbox"> elements in a parent <label> element, and removing the unnecessary <br /> elements along with the obtrusive in-line event-handlers in the HTML:

// a named function bound to an element via
// via JavaScript; the 'event' argument
// is passed automatically from the
// EventTarget.addEventListener() method:
function disableIfChecked(event) {

  // the event.target node is the node upon which
  // the listened-for event was originally triggered:
  let target = event.target;

  // 'this' is also passed from the
  // EventTarget.addEventListener() method; here
  // retrieved all <input> elements within the
  // <form> (the 'this'), convert that NodeList
  // explicitly to an Array and then filter that
  // Array using an Arrow function:
  Array.from(this.querySelectorAll('input')).filter(

    // we retain only those elements ('el') in the Array
    // which are not equal to, and therefore are not, the
    // changed element:
    el => el !== target

    // iterating over the filtered collection:
  ).forEach(

    // each <input> element remaining in the collection
    // will be disabled if the changed element is clicked,
    // or enabled if the changed element is no longer clicked:
    el => el.disabled = target.checked
  );
}

document.querySelector('#myForm').addEventListener('change', disableIfChecked);
/* Selecting the <label> element that follows
   an <input> element: */

input+label::before {
  /* Adding a line-feed character using the CSS
     'content' property of the pseudo-element
     to force each <label> to a new-line: */
  content: '\A';
  display: block;
}
<form id="myForm">

  <!-- the label element associates the text with the enclosed
       input, so clicking the text focuses that input element: -->
  <label>Checkbox 1: <input type="checkbox" name="checkbox1" id="checkboxOne" /></label>
  <input type="text" id="id1" name="name1" />

  <label>Checkbox 2: <input type="checkbox" name="checkbox2" id="checkboxTwo" /></label>
  <input type="text" id="id2" name="name3" />

  <label>Checkbox 3: <input type="checkbox" name="checkbox3" id="checkboxThree" /></label>
  <input type="text" id="id3" name="name3" />

</form>

JS Fiddles: commented, uncommented

In order to support browsers without support for ES6, the following is an alternative approach doing the same thing:

// a named function bound to an element via
// via JavaScript; the 'event' argument
// is passed automatically from the
// EventTarget.addEventListener() method:
function disableIfChecked(event) {

  // the event.target node is the node upon which
  // the listened-for event was originally triggered:
  let target = event.target;

  // 'this' is also passed from the
  // EventTarget.addEventListener() method; here
  // retrieved all <input> elements within the
  // <form> (the 'this'), convert that NodeList
  // explicitly to an Array by treating the NodeList
  // as an Array, using Function.prototype.call(),
  // and Array.prototype.slice():
  Array.prototype.slice.call(
    this.querySelectorAll('input')
  ).filter(function(el) {

    // we retain only those elements ('el') in the Array
    // which are not equal to, and therefore are not, the
    // changed element:
    return el !== target;

    // iterating over the filtered collection:
  }).forEach(function(el) {

    // each <input> element remaining in the collection
    // will be disabled if the changed element is clicked,
    // or enabled if the changed element is no longer clicked:
    el.disabled = target.checked;
  });
}

document.querySelector('#myForm').addEventListener('change', disableIfChecked);
/* Selecting the <label> element that follows
   an <input> element: */

input+label::before {
  /* Adding a line-feed character using the CSS
     'content' property of the pseudo-element
     to force each <label> to a new-line: */
  content: '\A';
  display: block;
}
<form id="myForm">

  <!-- the label element associates the text with the enclosed
       input, so clicking the text focuses that input element: -->
  <label>Checkbox 1: <input type="checkbox" name="checkbox1" id="checkboxOne" /></label>
  <input type="text" id="id1" name="name1" />

  <label>Checkbox 2: <input type="checkbox" name="checkbox2" id="checkboxTwo" /></label>
  <input type="text" id="id2" name="name3" />

  <label>Checkbox 3: <input type="checkbox" name="checkbox3" id="checkboxThree" /></label>
  <input type="text" id="id3" name="name3" />

</form>

JS Fiddles.

References:

Upvotes: 1

Freeman Lambda
Freeman Lambda

Reputation: 3655

It's usually best to use onchange instead of onclick event on inputs such as checkboxes, radiobuttons, or selects.

In order to make a general solution for as many inputs as you need, it's best to use document.querySelectorAll to fetch all inputs within the form. You can then iterate over all inputs and set their disabled property to the checked value of the targeted checkbox.

Solution snippet below:

function enableDisableAll(event) {
  var allInputs = document.querySelectorAll('#myForm input');

  allInputs.forEach(function(input) {
    if (input !== event.target) {
      input.disabled = event.target.checked;
    }
  });
}
<form id="myForm">

  Checkbox 1: <input type="checkbox" name="checkbox1" id="checkboxOne" onchange="enableDisableAll(event);" />
  <input type="text" id="id1" name="name1" /><br> Checkbox 2: <input type="checkbox" name="checkbox2" id="checkboxTwo" onchange="enableDisableAll(event);" />
  <input type="text" id="id2" name="name2" /><br> Checkbox 3: <input type="checkbox" name="checkbox3" id="checkboxThree" onchange="enableDisableAll(event);" />
  <input type="text" id="id3" name="name3" /><br>

</form>

An important detail here is that if you want to assign a typical event handler function directly to an HTML attribute, the function must have a single parameter explicitly named event. It is however recommended to assign event handlers in javascript and not in HTML. The syntax for that would be myCheckbox.addEventListener('change', enableDisableAll); You may want to add listeners to every checkbox, by iterating over a selector of all checkboxes.

Upvotes: 0

Related Questions