0

Below it's a very simple javascript function. When I click the button it's supposed to show me the value of the checked checkbox but it't prints out an error in the console saying the checkedValue is null?

I tried looping through the checkboxes and getting the checked one and i get the same error. I would really appreciate some help!

<body> <p id='txt'>here: </p> <button id="btn" type="button" onclick="ok" >Click </button> <input type="checkbox" class="ckb" value="1">one <input type="checkbox" class="ckb" value="2">two <input type="checkbox" class="ckb" value="3">three <script> var checkedValue = document.querySelectorAll('.ckb').checked; document.getElementById('btn').addEventListener('click', function(){ document.getElementById('txt').innerText = checkedValue.value ; }); </script> </body> 

Looping through the checkboxes

 var checkedValue; var inputElements = document.querySelectorAll('.ckb'); for(var i=0; i < inputElements.length; i++){ if(inputElements[i].checked===true){ checkedValue = inputElements[i]; break; } } 
4
  • checkedValue is a Boolean representing the checked state of the first .ckb element, and has no value property. You haven't shown your attempted loop, what are you trying to do? Commented Jan 17, 2021 at 20:25
  • You need to refer about document.querySelector('.ckb'). Also.checked gives a Boolean value Commented Jan 17, 2021 at 20:25
  • @DavidsaysreinstateMonica I updated the post with the looping part. I am trying to get the value of the checked checkbox. Commented Jan 17, 2021 at 20:34
  • Please share the full and exact error message, and your debugging attempts Commented Jan 17, 2021 at 21:02

2 Answers 2

1

With some minor adjustments, this should be what you are looking for.

 <body> <p id='txt'>here: </p> <button id="btn" type="button">Click </button> <input type="checkbox" class="ckb" value="1">one <input type="checkbox" class="ckb" value="2">two <input type="checkbox" class="ckb" value="3">three <script> document.getElementById('btn').addEventListener('click', function() { var chkbxElements = document.getElementsByClassName("ckb"); for (element of chkbxElements) { if (element.checked) { document.getElementById('txt').innerText = `here: ${element.value}`; } } }); </script> </body> 
Sign up to request clarification or add additional context in comments.

Comments

0

To directly address your question, the problem lies in the code:

// this line returns a NodeList of all elements matching the // supplied CSS selector ('.ckb'), this NodeList has no // 'checked' property, and so will ultimately return // undefined. var checkedValue = document.querySelectorAll('.ckb').checked; document.getElementById('btn').addEventListener('click', function(){ // here you try to access the 'value' property of the undefined // Object returned earlier, which returns null: document.getElementById('txt').innerText = checkedValue.value ; }); 

As an alternative, I would suggest something like the following:

// using a const to declare the element, since it's unlikely // you'll want to change which element triggers the function: const button = document.getElementById('btn'); //here we bind the anonymous function of EventTarget.addEventListener() // to the 'click' event upon that identified <button> element, using // Arrow function syntax (since we don't require access to the // 'this'): button.addEventListener('click', (e) => { // here we retrieve all elements which are checked (using the // CSS pseudo-class ':checked') and have the class of 'ckb': let checked = document.querySelectorAll('.ckb:checked'), // retrieving the element into which the output should be // displayed: output = document.querySelector('#txt'); // here we update the text-content (using the textContent property) // and set it equal to the results returned from: // first converting the NodeList of checked // into an Array, using Array.from(), using the // Array.prototype.map() method to iterate over that // Array: output.textContent = Array.from(checked).map( // returning the value of the element ('el'): (el) => el.value // joining those array elements together into a String, using // Array.prototype.join(), and appending a period for // grammatical correctness: ).join(', ') + '. '; }); 

const button = document.getElementById('btn'); button.addEventListener('click', (e) => { let checked = document.querySelectorAll('.ckb:checked'), output = document.querySelector('#txt'); output.textContent = Array.from(checked).map( (el) => el.value ).join(', ') + '. '; });
*, ::before, ::after { box-sizing: border-box; font-size: 1rem; line-height: 1.4; margin: 0; padding: 0; } #txt::before { content: 'Checked items: ' } #txt:empty::before { color: #999; content: 'No items checked.'; } input { margin-right: 0.5em; }
<p id='txt'></p> <button id="btn" type="button">Click</button> <label> <input type="checkbox" class="ckb" value="1">one </label> <label> <input type="checkbox" class="ckb" value="2">two </label> <label> <input type="checkbox" class="ckb" value="3">three </label>

JS Fiddle demo.

Note that I've also wrapped each <input> element within a <label> element, in order that clicking the text associated with each <input> also toggles the checked state of that element.

Using CSS generated content, I've taken the liberty of giving an indication of the current state; when the <p id="txt"> element is empty (matching the :empty pseudo-class, containing not even white-space) it shows the message "No items checked"), this may — or may not — represent a user-experience/interface improvement, but adjust to your own preference.

Further we move the event-binding out of the HTML mark-up, in order to reduce clutter in that mark-up, and reduce complications when it comes to future maintenance of the page.

You could, of course, bind the change event on the <input> elements themselves:

const inputs = document.querySelectorAll('.ckb'), output = () => { let results = document.querySelector('#txt'), checked = Array.from(inputs).filter( (el) => el.checked ); results.textContent = checked.length === 0 ? '' : checked.map( (el) => el.value ).join(', ') + '. '; }; inputs.forEach( (el) => el.addEventListener('change', output) ); 

// getting a NodeList of all elements matching the supplied // CSS selector: const inputs = document.querySelectorAll('.ckb'), // defining the function to bind as the event- // handler, using Arrow function syntax: output = () => { // retrieving the element to which the results // should be inserted: let results = document.querySelector('#txt'), // using Array.from() to convert the 'inputs' // variable to an Array, and then calling // Array.prototype.filter() to filter that // Array returning a new one: checked = Array.from(inputs).filter( // 'el' refers to the current Array-element // (node) of the Array we're iterating over, // el.checked is a Boolean, and // Array.protoype.filter() retains those Array- // elements the assessment of which returns a // true/truthy value (discarding those which do // not): (el) => el.checked ); // here we use a ternary - conditional operator - to first // check if the length of the checked Array is exactly zero; // if so we return an empty string; otherwise we return // the map of Array-element (node) values joined - as above - // with a comma and space, with an appended period: results.textContent = checked.length === 0 ? '' : checked.map( (el) => el.value ).join(', ') + '. '; }; // iterating over the NodeList of .ckb elements, with an // Arrow function, and in each iteration we bind the // output() function as the event-handler for the 'change' // event: inputs.forEach( (el) => el.addEventListener('change', output) );
*, ::before, ::after { box-sizing: border-box; font-size: 1rem; line-height: 1.4; margin: 0; padding: 0; } #txt::before { content: 'Checked items: '; } #txt:empty::before { color: #999; content: 'No items checked.'; }
<p id='txt'></p> <label> <input type="checkbox" class="ckb" value="1">one </label> <label> <input type="checkbox" class="ckb" value="2">two </label> <label> <input type="checkbox" class="ckb" value="3">three </label>

JS Fiddle demo.

References:

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.