选择输入收音机时更改最近 class 的样式 - Javascript

change style of closest class when input radio is selected - Javascript

我必须做一个非常简单的任务,但我想不出来。

我有一些卡片,用户可以使用单选按钮 select。我想在用户点击相关输入收音机时突出显示 selected 卡片。

我不明白我怎么能 select 最近 class 的 selected 收音机。

我的 HTML 看起来像这样:

<div class="box">
    <div class="box-content">
        <input type="radio" name="box-input">
        <label>Label One</label>
    </div>
</div>

<div class="box">
    <div class="box-content">
        <input type="radio" name="box-input">
        <label>Some Two</label>
    </div>
</div>

And so on...

<button onclick="submit()">Submit</button>

如果我这样做:

let boxes = document.querySelectAll('input');
const submit = () => {
    for (let i=0;i<boxes.length;i++) {
        boxes[i].checked? this.closest('.box').classList.add('selected'): console.log('nothing is selected')
    }
}

它说 this.closestundefined,只有当用户点击提交按钮时它才有效。

我想要做的只是在无线电输入 selected 时将 class 添加到 div .box,并在将状态更改为未selected.

如果可能的话,我也想避免内联 HTML "onclick"。

请纯javascript只

编辑

根据@somethinghere 的建议,我将 onchange="change(this)" 添加到每个输入收音机中,并以这种方式更改我的脚本:

const change = el => {
    el.checked?el.closest('.box').classList.add('selected'):el.closest('.box').classList.remove('selected')
;

有效,当我点击输入收音机时它会添加 class selected。但是如果我点击另一个输入,那么 class selected 不会被删除。

建议?

添加了代码以在选择输入收音机时更改最近 class 的样式

var radioAll = document.querySelectorAll('input');

for(var i = 0; i < radioAll.length; i++) 
{
   radioAll[i].onclick = function() 
   {
      //remove selected class from all box classs
      var boxElems = document.querySelectorAll(".box");
      [].forEach.call(boxElems, function(el) {
         el.classList.remove("selected");
      });
      if(this.checked)
      {
         this.closest('.box').classList.add('selected');
      }    
    };
}
.selected{
background-color: coral;
}
<div class="box">
    <div class="box-content">
        <input type="radio" name="box-input">
        <label>Label One</label>
    </div>
</div>

<div class="box">
    <div class="box-content">
        <input type="radio" name="box-input">
        <label>Some Two</label>
    </div>
</div>

And so on...

<button onclick="submit()">Submit</button>

虽然你已经接受了一个答案,但我想我会添加一个替代方法:

// get a reference to the <button> element; here you only have the one <button>,
// so document.querySelector() will suffice (as it returns either the first
// Node that matches the supplied selector or null):
let submitButton = document.querySelector('button'),
  inputs = document.querySelectorAll('input');

// here we use the same Arrow function syntax, which does not - by design - get
// its own 'this' reference:
const submit = () => {

  // since we have the <input> elements already we use that, along with the
  // NodeList.prototype.forEach() method:
  inputs.forEach(
  
    // here 'input' is a reference to the current <input> element of the
    // NodeList of <input> elements over which we're iterating.
    // we use Element.closest() to find the relevant '.box' element, and
    // use the Element.classList API to toggle the 'hasSelected'
    // class-name based on the supplied 'switch', the 'input.checked'; if
    // 'input.checked' is true the class-name is added to the '.box', if
    // 'input.checked' is false the class-name is removed (if the class-name
    // is already present, or not-present, when it's added or removed no
    // error is thrown and it presents no problem):
    (input) => input.closest('.box').classList.toggle('hasSelected', input.checked)
  )
}

// using the EventTarget.addEventListener() method, in place of the obtrusive
// 'onclick' in-line event-handling; here we bind the submit() function 
// (note the deliberate lack of parentheses) as the event-handler for the
// 'click' event:
submitButton.addEventListener('click', submit);
*,
::before,
::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  font-size: 1rem;
  line-height: 1.5;
}

body>div {
  display: flex;
  justify-content: space-between;
  width: 50vw;
  margin: 1em auto;
}

div.box {
  display: grid;
  grid-template-columns: 1fr 30px;
  grid-gap: 0 10px;
  border: 2px solid transparent;
  padding: 0.5em;
  border-radius: 1em;
}

div.box.hasSelected {
  border-color: limegreen;
}

div.box.hasSelected::after {
  display: contents;
  content: '✓';
  font-weight: bold;
  color: limegreen;
}
<div>
  <div class="box">
    <div class="box-content">
      <label><input type="radio" name="box-input">
      Label One</label>
    </div>
  </div>

  <div class="box">
    <div class="box-content">
      <label><input type="radio" name="box-input">
      Some Two</label>
    </div>
  </div>

  <button>Submit</button>
</div>

JS Fiddle demo.

参考文献: