【问题标题】:Limit Checkboxes from getting checked when two separate drop-down options are selected?限制复选框从选中两个单独的下拉选项时检查?
【发布时间】:2020-09-04 18:20:31
【问题描述】:

我试图在选择特定的值组合时限制复选框选项。

我有一个名为toneCapArray 的检查组,我想在选择value="bp"value="master-tone" 时限制复选框。这些值在最后两个选择框中指定。

我遇到了一个障碍,因为我学习 JS 才几个月。选择这两个值时,我无法运行该函数。

checkboxlimit(toneCapArray, 1);函数直接在函数定义下运行时,它就起作用了。

但是,当我通过查看两者是否为真来调用该函数时:(item.value === "bp" && item.value === "master-tone") 它不起作用,并且我没有收到任何错误或任何有助于调试它的东西。

重现:

  1. 取消注释 fiddle 的第 28 行并尝试选择 3 个复选框。
  2. 注释第 28 行和取消注释第 37 行
  3. 在选择框 3 和 4 中选择 Master Tone & Blender Pot,然后尝试再次选中 3 个复选框。

补充问题:

  1. 我在 8 个选择框上有一个事件监听器,但我只需要事件监听器来监听两个。是否可以听多个选择框并听值?
  2. 我计划在选择单独的单选按钮时扩展它以运行相同的函数但使用不同的参数,但我想我会从这里开始。我希望它具有可扩展性。

小提琴:

JS FIDDLE

function masterCheckboxLimit() {
  //set up the locations:

  const toneCapArray = document.getElementsByName("addon-3987-tone-cap-2[]");
  var select = document.querySelectorAll("select");

  //limit the checkboxes:

  function checkboxlimit(checkgroup, limit) {
    for (var i = 0; i < checkgroup.length; i++) {
      checkgroup[i].addEventListener("click", function () {
        var checkedcount = 0;
        for (var i = 0; i < checkgroup.length; i++) {
          checkedcount += checkgroup[i].checked ? 1 : 0;
          if (checkedcount > limit) {
            window.alert("You can only select a maximum of " + limit + " tone caps");
            this.checked = false;
          }
        }
      });
    }
  }


  //select the select boxes and add a change event listener

  select.forEach((item) => {
    item.addEventListener("change", (e) => {

      if (document.getElementsByName("pa_tone-pot-1")[0].value === "master-tone" && document.getElementsByName("pa_tp-2")[0].value === "bp"){
    checkboxlimit(toneCapArray, 1); //I want this function to run when both are true above
    });
  });
}
masterCheckboxLimit();
<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>

  <body>
    <h1>Product Options:</h1>
    <p>
      <select name="pickup_location" id="" label="">
        <option value="">Select an Option</option>
        <option value="complete_set">Complete Set</option>
        <option value="neck">Neck</option>
        <option value="bridge">Bridge</option>
      </select>
    </p>

    <p>
      <select name="pickup_color" id="" label="">
        <option value="">Select an Option</option>
        <option value="black">Black</option>
        <option value="white">White</option>
      </select>
    </p>

    <p>
      <select name="tone_pot_1" id="" label="">
        <option value="">Select an Option</option>
        <option value="neck_middle_tone">Neck and Middle Tone</option>
        <option value="master-tone">Master Tone</option>
      </select>
    </p>
    <p>
      <select name="tone_pot_2" id="" label="">
        <option value="">Select an Option</option>
        <option value="bp">Blender Pot</option>
        <option value="bridge-tone">Bridge Tone</option>
      </select>
    </p>

    <h2>Add Ons:</h2>

    <p><input type="checkbox" id="1" name="addon-3987-tone-cap-2[]" value="Cap 1" label="Cap 1" /><label for="1">Tone Cap 1</label></p>
    <p><input type="checkbox" id="2" name="addon-3987-tone-cap-2[]" value="Cap 2" label="Cap 2" /><label for="2">Tone Cap 2</label></p>
    <p><input type="checkbox" id="3" name="addon-3987-tone-cap-2[]" value="Cap 3" label="Cap 3" /><label for="3">Tone Cap 3</label></p>
  </body>

</html>

我的代码有什么明显的地方吗?

【问题讨论】:

  • 我在您的代码中发现了 2 个问题
  • 请注意,checkboxlimit 每次调用时都会添加一个事件监听器,但不会删除任何事件监听器,因此当单击检查组时,它将运行每个事件自页面加载以来一直添加的侦听器。这通常是一件坏事(tm)。
  • 您可能需要document.getElementsByName('tone_pot_2')[0].value === "bp" 而不是item.value === "bp",因为该选择是唯一具有该值的选择。其他值也是如此。
  • 谢谢。我在我的代码上更改了它们。您将如何操作代码以删除事件侦听器?
  • 这有可能吗? item.value === "bp" && item.value === "master-tone"

标签: javascript html forms dom addeventlistener


【解决方案1】:

我发现您的代码中有 2 个问题

1 - 这将永远是 false 所以它永远不会进入 if 块。

if (item.value === "bp" && item.value === "master-tone")

因为"bp" !== "master-tone" item.value 不能两者都相等(除非你有一个 hacky getter)

2 - 您正在寻找一个值 bp 但该值不在 HTML 代码中

这也可能发挥作用,因为您正在寻找不存在的东西。

更新:

我认为以下可运行的 sn-p 会做你想做的事,检查一下。

function masterCheckboxLimit() {
  const tone_pot_1 = document.querySelector('#tone_pot_1')
  const tone_pot_2 = document.querySelector('#tone_pot_2')
  const checkboxes = document.querySelectorAll('input[type=checkbox]')

  let maxNumberOfMarkedCheckBoxesAllowed = 3
  let curNumberOfMarkedCheckBoxesAllowed = 0

  function selectsOnChangeEvent(e) {
    if (tone_pot_1.value === 'master-tone' && tone_pot_2.value === 'bp') {
      maxNumberOfMarkedCheckBoxesAllowed = 1
      if (curNumberOfMarkedCheckBoxesAllowed > maxNumberOfMarkedCheckBoxesAllowed) {
        checkboxes.forEach(checkbox => {
          checkbox.checked = false
        })
        curNumberOfMarkedCheckBoxesAllowed = 0
        alert(`If you have master-tone and bp you can only check 1 box. Please make your selection again`)
      }
    } else {
      maxNumberOfMarkedCheckBoxesAllowed = 3
    }
  }

  function checkBoxOnClickEvent(e) {
    const number = this.checked ? 1 : -1

    if (curNumberOfMarkedCheckBoxesAllowed + number > maxNumberOfMarkedCheckBoxesAllowed) {
      alert('Nope')
      return e.preventDefault()
    }

    curNumberOfMarkedCheckBoxesAllowed += number

    console.log({
      number,
      curNumberOfMarkedCheckBoxesAllowed,
      maxNumberOfMarkedCheckBoxesAllowed
    })
  }

  [tone_pot_1, tone_pot_2].forEach((checkbox) => {
    checkbox.addEventListener('change', selectsOnChangeEvent)
  })


  checkboxes.forEach((checkbox) => {
    checkbox.addEventListener('click', checkBoxOnClickEvent)
  })
}

masterCheckboxLimit();
label { cursor: pointer; }
#selects, #checkboxes { float: left }
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Document</title>
</head>

<body>
  <div id="selects">
    <h1>Product Options:</h1>
    <p>
      <select name="pickup_location" id="pickup_location" label="">
        <option value="">Select an Option</option>
        <option value="complete_set">Complete Set</option>
        <option value="neck">Neck</option>
        <option value="bridge">Bridge</option>
      </select>
    </p>

    <p>
      <select name="pickup_color" id="pickup_color" label="">
        <option value="">Select an Option</option>
        <option value="black">Black</option>
        <option value="white">White</option>
      </select>
    </p>

    <p>
      <select name="tone_pot_1" id="tone_pot_1" label="">
        <option value="">Select an Option</option>
        <option value="neck_middle_tone">Neck and Middle Tone</option>
        <option value="master-tone">Master Tone</option>
      </select>
    </p>
    <p>
      <select name="tone_pot_2" id="tone_pot_2" label="">
        <option value="">Select an Option</option>
        <option value="bp">Blender Pot</option>
        <option value="bridge-tone">Bridge Tone</option>
      </select>
    </p>
  </div>
  <div id="checkboxes">
    <h2>Add Ons:</h2>
    <p><input type="checkbox" id="1" name="addon-3987-tone-cap-2[]" value="Cap 1" label="Cap 1" /><label for="1">Tone Cap 1</label></p>
    <p><input type="checkbox" id="2" name="addon-3987-tone-cap-2[]" value="Cap 2" label="Cap 2" /><label for="2">Tone Cap 2</label></p>
    <p><input type="checkbox" id="3" name="addon-3987-tone-cap-2[]" value="Cap 3" label="Cap 3" /><label for="3">Tone Cap 3</label></p>
  </div>
</body>

</html>

【讨论】:

  • bp 在选择框 4 中。&lt;option value="bp"&gt;Blender Pot&lt;/option&gt;
  • 嘿@Mestre San,您将如何重写此语句以使两个值都为真?
  • @Sackadelic,他已经在他的代码中为您完成了它if (tone_pot_1.value === 'master-tone' &amp;&amp; tone_pot_2.value === 'bp') 。原始代码的问题之一是 item 循环中的 select.forEach 变量永远不可能是两个不同的值。每次迭代都会重新创建变量,因为它本质上运行 4 个不同的函数,一个用于运行时创建的每个选择 var select = document.querySelectorAll("select"); 继续弄清楚闭包和作用域在 js 中是如何工作的,你会得到它:developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
  • 非常感谢,@Mestre San。我能够以不同的方式做到这一点,但你的提示帮助我完成了它!我被困在了这一点上。再次感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-21
  • 2015-01-31
  • 1970-01-01
相关资源
最近更新 更多