0

I am trying to make a button to check all checkboxes in a single line of a button onclick. Let's assume some checkboxes...

<input name="chk1" type="checkbox" class="post_dest_check" value="1" />Opt1
<input name="chk2" type="checkbox" class="post_dest_check" value="2" />Opt2
<input name="chk3" type="checkbox" class="post_dest_check" value="3" />Opt3

<button type="button" class="action" onClick="document.getElementsByClassName('post_dest_check').map((elm)=>{ elm.checked = true;});">Todos</button>

When clicked, will give me error

SyntaxError: Unexpected token ')'".

I also have tried with forEach.

Why? What's wrong? Is there a way to do this without heaving to write a script in the root to call from button?

Edit: I think I miss some explanation about why I wish to do like this, a script inside the onClick property. I have many forms that are loaded into the page as needed. By making a script in the page instead of in the form, I will have to create a "standard" to my forms, so the script can find the elements in the form every time is loaded. If I change one form, maybe I will have to change all of them and the script. Not a catastrophe, I just thought maybe a script inside the form can avoid this complexity - a built in automation. Of course, if possible and advisable.

0

2 Answers 2

2

There are a few things wrong here:

  1. Do not use inline event attributes like onclick. Instead of using this 25+ year old technique that pre-dates standards and causes scalability and this binding issues, use the standard .addEventListener() that is separated from your HTML (which makes debugging easier by the way).

  2. Do not use getElementsByClassName() as this returns a live node list that can cause performance issues, especially in looping situations.

  3. .map() returns a new array, which in your use case is not needed and therefore a waste of resources. Instead, .forEach() is the better approach.

  4. Don't bother with self-terminating XHTML syntax. It buys you nothing and can add confusion as to where it can/can't be used.

In the code below, "event delegation" is used so that you can have one event handler handle any set of checkboxes that are within their own form.

// Set up an event handler at a common ancestor of all the elements you wish to handle
document.querySelector("section").addEventListener("click", function(event){
  // Check to see if the event was triggered by an element you care to handle
  if(event.target.classList.contains("action")){
    // Get your reference to all the checkboxes in that form
    // (.closest searches for the nearest matching ancestor) and
    // loop over the checkboxes with the .forEach() method that works on node lists
    event.target.closest("form").querySelectorAll("input.post_dest_check").forEach(function(box){
      box.checked = true;
    });
  }
});
<section>
<fieldset>
  <legend>Form 1</legend>
  <form>
    <input name="chk1" type="checkbox" class="post_dest_check" value="1">Opt1
    <input name="chk2" type="checkbox" class="post_dest_check" value="2">Opt2
    <input name="chk3" type="checkbox" class="post_dest_check" value="3">Opt3
    <button type="button" class="action">Todos</button>
 </form>
</fieldset>

<fieldset>
  <legend>Form 2</legend>
  <form>
    <input name="chk1" type="checkbox" class="post_dest_check" value="1">Opt1
    <input name="chk2" type="checkbox" class="post_dest_check" value="2">Opt2
    <input name="chk3" type="checkbox" class="post_dest_check" value="3">Opt3
    <input name="chk3" type="checkbox" class="post_dest_check" value="3">Opt4    
    <button type="button" class="action">Todos</button>
 </form>
</fieldset>

<fieldset>
  <legend>Form 3</legend>
  <form>
    <input name="chk1" type="checkbox" class="post_dest_check" value="1">Opt1
    <input name="chk2" type="checkbox" class="post_dest_check" value="2">Opt2
    <button type="button" class="action">Todos</button>
 </form>
</fieldset>
</section>

Sign up to request clarification or add additional context in comments.

5 Comments

This is precisely what I wish to avoid. The point is to load a form with this "build in" automation, since HTML5 don't have (as far I know) "check all" feature as clear form button. My goal is a script inside onClick property - is this possible?
@Gustavo I really don't know what you are saying. Why is this modern, standards-based approach what you want to avoid? What doesn't this solution do that you need it to? All you need to do is include the JavaScript within a <script> element just prior to the closing body element and it works.
I have a lot of forms that will be load eventually, as needed. Is not a whole page loaded, just the form. So after loading I will have to add the event to the button and build the array, always to every form. I will have to create a "standard", a smart script that find and activate the automation. I'm not saying your solution is wrong, I just thought about avoiding this two documents solution for a single document, a form with build in automation that I can change later without to worry with the counterpart script.
I see. There's a simple solution for that called "event delegation" which allows for an event to bubble up to an ancestor element and be handled there. This way, you can write one handler for many elements without even knowing what they are. I will update the answer to demonstrate this.
Yes! Now you got it. I did put in my page ini but getting all body instead section. Now is just to load the for with the right classes and voilá, I have my check all button. I still thought would be better some script in the form. But I have to admit a script as @JD Byrnes suggested is kinda outside good practices, I was thinking about some hack, instead of a full code.
1

How to check all checkboxes using javascript in onClick button?

for(el of document.getElementsByTagName('input')){if(el.type==="checkbox")el.checked=true;}

However, if you only want checkboxes with the class 'post_dest_check' you could be a little more specific.

for(el of document.getElementsByClassName('post_dest_check')){if(el.constructor.name==="HTMLInputElement"&&el.type==="checkbox")el.checked=true;}

I've only left out optional spaces as you've indicated you were going to use this in an inline onClick event handler.

11 Comments

Both .,getElementsByTagName() and .getElementsByClassName() return live node lists which adversely affect performance and should be avoided.
Thanks for the suggestion. I have changed a bit of my mind and decided to use the Scott's code. To put all this code inside a property is really... ugly, I must admit. I was thinking about some small code like a hack, that's why I was trying with map and forEach.
@ScottMarcus It's irrelevant to me about the minor performance impact. OP had indicated he needed to do it inline, and this was the best solution for that.
It's far from minor. Those are legacy methods and should be avoided. And, those two methods are hardly the only ones that can be used inline (.querySelectorAll(), .querySelector()).
Benchmarking shows the opposite of what you're stating, and it seems like the source for your references is... yourself? measurethat.net/Benchmarks/ShowResult/284968 On my computer I can do 9,264,681 calls to getElementsByClassName() per second, with only 8,001,476 per second to querySelector(). If you're gonna continue calling people out, feel free to add some reliable information. If you don't call -17.0401439 nanoseconds minor, then what is?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.