简体   繁体   中英

Add/Remove class on click in pure JS

I've always used jQuery , it's easy there, but I decided to switch to pure JS and ran into difficulties. When I click on the button, I want the crossOut class to be added to the 3 elements with the appOrd class, and the button itself becomes inactive (the bootstrap class - disabled ). And the second button, Resume , does the opposite. But nothing works, please tell me what is the problem?

PSI suppose there is an error in the const , perhaps it cannot be used like that?

UPD-1. Barmar suggested a typo, corrected it.

UPD-2. It is necessary that the class is added only to the current row of the table.

 const hasClass = document.querySelector('.appOrd').classList.contains('crossOut'); document.querySelector('.completeBtn').onclick=function(e) { e.preventDefault(); if(.hasClass) { document.querySelector('.appOrd').classList;add('crossOut'). document.querySelector('.resumeBtn').classList;remove('disabled'). this.classList;add('disabled'). } } document.querySelector('.resumeBtn').onclick=function(e) { e;preventDefault(). if(hasClass) { document.querySelector('.appOrd').classList;remove('crossOut'). document.querySelector('.completeBtn').classList;remove('disabled'). this.classList;add('disabled'); } }
 .crossOut{ text-decoration: line-through; }
 <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.min.js"></script> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet"/> <table class="table table-bordered"> <thead> <tr class="text-center"> <th scope="col">Name</th> <th scope="col">Phone number</th> <th scope="col">Application time</th> <th scope="col">Status</th> </tr> </thead> <tbody> <tr class="text-center"> <td scope="row" class="appOrd">Name</td> <td class="appOrd">Phone number</td> <td class="appOrd">2021-02-07 08:40:48</td> <td> <a class="btn btn-success resumeBtn disabled" href="#">Resume</a> <a class="btn btn-danger completeBtn" href="#">Complete</a> </td> </tr> </tbody> </table>

You need to use querySelectorAll() to select more than one element, and then update the class on all of them. This can be done with .forEach() to loop over them.

Similarly, use querySelectorAll() to add the onclick handler to each of the buttons.

 document.querySelectorAll('.completeBtn').forEach(el => el.onclick = function(e) { e.preventDefault(); let row = this.closest("tr"); row.querySelectorAll('.appOrd').forEach(el => el.classList.add('crossOut')); row.querySelector('.resumeBtn').classList.remove('disabled'); this.classList.add('disabled'); }); document.querySelectorAll('.resumeBtn').forEach(el => el.onclick = function(e) { e.preventDefault(); let row = this.closest("tr"); row.querySelectorAll('.appOrd').forEach(el => el.classList.remove('crossOut')); row.querySelector('.completeBtn').classList.remove('disabled'); this.classList.add('disabled'); });
 .crossOut { text-decoration: line-through; }
 <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.min.js"></script> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" /> <table class="table table-bordered"> <thead> <tr class="text-center"> <th scope="col">Name</th> <th scope="col">Phone number</th> <th scope="col">Application time</th> <th scope="col">Status</th> </tr> </thead> <tbody> <tr class="text-center"> <td scope="row" class="appOrd">Name</td> <td class="appOrd">Phone number</td> <td class="appOrd">2021-02-07 08:40:48</td> <td> <a class="btn btn-success resumeBtn disabled" href="#">Resume</a> <a class="btn btn-danger completeBtn" href="#">Complete</a> </td> </tr> <tr class="text-center"> <td scope="row" class="appOrd">Name 2</td> <td class="appOrd">Phone number 2</td> <td class="appOrd">2021-02-06 09:00:50</td> <td> <a class="btn btn-success resumeBtn disabled" href="#">Resume</a> <a class="btn btn-danger completeBtn" href="#">Complete</a> </td> </tr> </tbody> </table>

the buttons are for the row that the they are in, so it is better to do it this way

 const resume = (src, enable) => { const tr = src.parentElement.parentElement; const nameElts = tr.querySelectorAll('.appOrd'); if (enable) { nameElts.forEach(e => e.classList.remove('crossOut')); } else { nameElts.forEach(e => e.classList.add('crossOut')); } const completeBtn = tr.querySelector(".completeBtn"); const resumeBtn = tr.querySelector(".resumeBtn"); if (enable) { completeBtn.classList.remove('disabled'); resumeBtn.classList.add('disabled'); } else { resumeBtn.classList.remove('disabled'); completeBtn.classList.add('disabled'); } } document.querySelectorAll(".completeBtn").forEach(elt => { elt.onclick = () => { resume(event.target, false); } }); document.querySelectorAll('.resumeBtn').forEach(elt => { elt.onclick = () => { resume(event.target, true); } });
 .crossOut { text-decoration: line-through; }
 <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.min.js"></script> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" /> <table class="table table-bordered"> <thead> <tr class="text-center"> <th scope="col">Name</th> <th scope="col">Phone number</th> <th scope="col">Application time</th> <th scope="col">Status</th> </tr> </thead> <tbody> <tr class="text-center"> <td scope="row" class="appOrd">Name</td> <td class="appOrd">Phone number</td> <td class="appOrd">2021-02-07 08:40:48</td> <td> <a class="btn btn-success resumeBtn disabled" href="#">Resume</a> <a class="btn btn-danger completeBtn" href="#">Complete</a> </td> </tr> <tr class="text-center"> <td scope="row" class="appOrd">Name1</td> <td class="appOrd">Phone number1</td> <td class="appOrd">2021-02-08 08:40:48</td> <td> <a class="btn btn-success resumeBtn disabled" href="#">Resume</a> <a class="btn btn-danger completeBtn" href="#">Complete</a> </td> </tr> </tbody> </table>

I'm not sure this is best approach OR not.

You can query the table rows ( tbody tr ) and add handlers by querying the Complete and Resume buttons and toggle the classes based clicks. In this way, you can handle the rows( tr ) smoothly.

 const rows = document.querySelectorAll('tbody tr') rows.forEach(row => { const completeBtn = row.querySelector('.completeBtn'); const resumeBtn = row.querySelector('.resumeBtn'); const appOrds = row.querySelectorAll('.appOrd'); completeBtn.addEventListener('click', function(e) { e.preventDefault(); appOrds.forEach(el => el.classList.add('crossOut')); resumeBtn.classList.remove('disabled'); this.classList.add('disabled'); }) resumeBtn.addEventListener('click', function(e) { e.preventDefault(); appOrds.forEach(el => el.classList.remove('crossOut')); completeBtn.classList.remove('disabled'); this.classList.add('disabled'); }) })
 .crossOut{ text-decoration: line-through; }
 <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.min.js"></script> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet"/> <table class="table table-bordered"> <thead> <tr class="text-center"> <th scope="col">Name</th> <th scope="col">Phone number</th> <th scope="col">Application time</th> <th scope="col">Status</th> </tr> </thead> <tbody> <tr class="text-center"> <td scope="row" class="appOrd">Name</td> <td class="appOrd">Phone number</td> <td class="appOrd">2021-02-07 08:40:48</td> <td> <a class="btn btn-success resumeBtn disabled" href="#">Resume</a> <a class="btn btn-danger completeBtn" href="#">Complete</a> </td> </tr> <tr class="text-center"> <td scope="row" class="appOrd">Name</td> <td class="appOrd">Phone number</td> <td class="appOrd">2021-02-07 08:40:48</td> <td> <a class="btn btn-success resumeBtn disabled" href="#">Resume</a> <a class="btn btn-danger completeBtn" href="#">Complete</a> </td> </tr> </tbody> </table>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM