对一组复选框使用 HTML5“必需”属性?

Posted

技术标签:

【中文标题】对一组复选框使用 HTML5“必需”属性?【英文标题】:Using the HTML5 "required" attribute for a group of checkboxes? 【发布时间】:2011-09-07 06:58:47 【问题描述】:

使用支持 html5 的较新浏览器时(例如 FireFox 4); 并且表单字段具有属性required='required'; 并且表单字段为空/空白; 并单击提交按钮; 浏览器检测到“必填”字段为空,因此不提交表单; 相反,浏览器会显示提示,要求用户在字段中输入文本。

现在,我有一个复选框,而不是单个文本字段,其中至少一个应该由用户检查/选择。

如何在这组复选框上使用 HTML5 required 属性? (由于只需要检查一个复选框,我不能将required 属性放在每个复选框上)

ps。我正在使用simple_form,如果这很重要的话。


更新

HTML 5 multiple attribute 在这里有用吗?有没有人用它来做类似于我的问题的事情?

更新

HTML5 规范不支持此功能似乎ISSUE-111: What does input.@required mean for @type = checkbox?

(问题状态:问题已被标记为已关闭且无偏见。) 还有here is the explanation。

更新 2

这是一个老问题,但想澄清一下,这个问题的初衷是能够在不使用 javascript 的情况下完成上述操作 - 即使用 HTML5 方法。回想起来,我应该让“没有 Javascript”更明显。

【问题讨论】:

这是一个很好的问题,适用于作为数组(包括文本输入)的任何表单输入,您希望至少有一个带有值的项目或检查(但不是任何特定的项目) . Demo我认为可能没有办法做到这一点,但我希望有。 (顺便说一句,什么语言、框架或库都没有关系,它是严格的 HTML5) 感谢您添加 JSFiddle 演示。希望有一些 HTML5 方式来做到这一点,否则可能不得不使用 JQuery 和隐藏字段或其他东西来汇总一些解决方案。 如果您想回退到 javascript(并且您正在使用 jQuery),无需“汇总”任何内容,请使用高度成熟的验证插件:bassistance.de/jquery-plugins/jquery-plugin-validation @natedavisolds,我认为这种用法在某些 UI 中很有用 - IMO,选择多个复选框对最终用户来说更直观,尤其是当复选框的数量很少时 - 而不是单击+select 与多选框一样。 附带说明,您不需要整个 required='required' 位;只需输入“必需”就足够了。 【参考方案1】:

不幸的是,HTML5 没有提供开箱即用的方式来做到这一点。

但是,使用 jQuery,您可以轻松控制复选框组是否具有至少一个选中元素。

考虑以下 DOM sn-p:

<div class="checkbox-group required">
    <input type="checkbox" name="checkbox_name[]">
    <input type="checkbox" name="checkbox_name[]">
    <input type="checkbox" name="checkbox_name[]">
    <input type="checkbox" name="checkbox_name[]">
</div>

你可以使用这个表达式:

$('div.checkbox-group.required :checkbox:checked').length > 0

如果至少检查了一个元素,则返回true。 在此基础上,您可以实施验证检查。

【讨论】:

@Clijsters 问题是关于 HTML5 的实现方式 - 不是使用 Javascript(当然,在 Javascript 中可以使用各种解决方案) @Zabba 但是这个答案说。如何在 html5 中编写 不幸的是 HTML5 没有提供开箱即用的方式来做到这一点 足够公平@Clijsters 这是setCustomValidity***.com/a/30222924的最佳实现【参考方案2】:

这是一个简单的技巧。这是一个 jQuery 代码,它可以通过更改 required 属性(如果选中任何一个)来利用 html5 验证。以下是您的 html 代码(确保为组中的所有元素添加所需的内容。)

<input type="checkbox" name="option[]" id="option-1" value="option1" required/> Option 1
<input type="checkbox" name="option[]" id="option-2" value="option2" required/> Option 2
<input type="checkbox" name="option[]" id="option-3" value="option3" required/> Option 3
<input type="checkbox" name="option[]" id="option-4" value="option4" required/> Option 4
<input type="checkbox" name="option[]" id="option-5" value="option5" required/> Option 5

以下是 jQuery 脚本,如果选择了任何一个,它将禁用进一步的验证检查。使用名称元素选择。

$cbx_group = $("input:checkbox[name='option[]']");
$cbx_group = $("input:checkbox[id^='option-']"); // name is not always helpful ;)

$cbx_group.prop('required', true);
if($cbx_group.is(":checked"))
  $cbx_group.prop('required', false);

这里的小问题:由于您使用的是 html5 验证,因此请确保在验证之前执行此操作,即在表单提交之前。

// but this might not work as expected
$('form').submit(function()
  // code goes here
);

// So, better USE THIS INSTEAD:
$('button[type="submit"]').on('click', function() 
  // skipping validation part mentioned above
);

【讨论】:

虽然可以通过 Javascript 实现,但我一直在寻找不使用 Javascript 的解决方案。 我认为这是迄今为止最好的答案。是的,它使用 javascript,但它使用 HTML5 的验证,而不是弹出 JavaScript 警报。其他答案使用 JS 和 JS 弹出窗口。 这真是太好了。确保在前两行 jQuery 行中选择一个(第二行抵消了第一行)。还要确保将“选项”更改为选项的名称。 鉴于 HTML5 本身不支持此功能,这确实应该是公认的答案!我不想只为我网站上的单个表单上的一组复选框字段实现我自己的验证库。【参考方案3】:

HTML5 不直接支持要求在一个复选框组中只选中一个/至少一个复选框。这是我使用 Javascript 的解决方案:

HTML

<input class='acb' type='checkbox' name='acheckbox[]' value='1' onclick='deRequire("acb")' required> One
<input class='acb' type='checkbox' name='acheckbox[]' value='2' onclick='deRequire("acb")' required> Two

JAVASCRIPT

       function deRequireCb(elClass) 
            el=document.getElementsByClassName(elClass);

            var atLeastOneChecked=false;//at least one cb is checked
            for (i=0; i<el.length; i++) 
                if (el[i].checked === true) 
                    atLeastOneChecked=true;
                
            

            if (atLeastOneChecked === true) 
                for (i=0; i<el.length; i++) 
                    el[i].required = false;
                
             else 
                for (i=0; i<el.length; i++) 
                    el[i].required = true;
                
            
        

javascript 将确保至少选中一个复选框,然后取消对整个复选框组的要求。如果选中的一个复选框变为未选中,那么它将再次要求所有复选框!

【讨论】:

一个非常好的和干净的解决方案。 Wish 可以给予超过 +1 票。 同意@Sonal!感谢您提供此解决方案,布赖恩! 最干净的解决方案...! 我喜欢这个解决方案,因为它可以更容易地用于验证同一表单上不同的复选框组。【参考方案4】:

我想没有标准的 HTML5 方法可以做到这一点,但如果你不介意使用 jQuery 库,我已经能够使用 webshims' "group-required" 验证实现“复选框组”验证特点:

docs for group-required 说:

如果复选框具有“group-required”类,则至少有一个 表单/文档中具有相同名称的复选框必须是 检查。

下面是一个你将如何使用它的例子:

<input name="checkbox-group" type="checkbox" class="group-required" id="checkbox-group-id" />
<input name="checkbox-group" type="checkbox" />
<input name="checkbox-group" type="checkbox" />
<input name="checkbox-group" type="checkbox" />
<input name="checkbox-group" type="checkbox" />

我主要使用 webshims 来填充 HTML5 功能,但它也有一些很棒的可选扩展,比如这个。

它甚至允许您编写自己的自定义有效性规则。例如,我需要创建一个不基于输入名称的复选框组,所以我写了my own validity rule for that...

【讨论】:

【参考方案5】:

受@thegauraw 和@Brian Woodward 的回答启发,我为 JQuery 用户整理了一些内容,包括自定义验证错误消息:

$cbx_group = $("input:checkbox[name^='group']");
$cbx_group.on("click", function() 
    if ($cbx_group.is(":checked")) 
        // checkboxes become unrequired as long as one is checked
        $cbx_group.prop("required", false).each(function() 
            this.setCustomValidity("");
        );
     else 
        // require checkboxes and set custom validation error message
        $cbx_group.prop("required", true).each(function() 
            this.setCustomValidity("Please select at least one checkbox.");
        );
    
);

请注意,我的表单默认选中了一些复选框。

也许你们中的一些 JavaScript/JQuery 向导可以更加严格?

【讨论】:

【参考方案6】:

我们也可以用html5轻松做到这一点,只需要添加一些jquery代码

Demo

HTML

<form>
 <div class="form-group options">
   <input type="checkbox" name="type[]" value="A" required /> A
   <input type="checkbox" name="type[]" value="B" required /> B
   <input type="checkbox" name="type[]" value="C" required /> C
   <input type="submit">
 </div>
</form>

jQuery

$(function()
    var requiredCheckboxes = $('.options :checkbox[required]');
    requiredCheckboxes.change(function()
        if(requiredCheckboxes.is(':checked')) 
            requiredCheckboxes.removeAttr('required');
         else 
            requiredCheckboxes.attr('required', 'required');
        
    );
);

【讨论】:

【参考方案7】:

我在一组复选框中添加了一个不可见的收音机。 当至少一个选项被选中时,收音机也被设置为选中。 当所有选项都被取消时,收音机也被设置为取消。 因此,表单使用单选提示“请检查至少一个选项”

您不能使用display: none,因为收音机无法聚焦。 我使单选框的大小等于整个复选框的大小,因此在出现提示时会更加明显。

HTML

<form>
  <div class="checkboxs-wrapper">
    <input id="radio-for-checkboxes" type="radio" name="radio-for-required-checkboxes" required/>
    <input type="checkbox" name="option[]" value="option1"/>
    <input type="checkbox" name="option[]" value="option2"/>
    <input type="checkbox" name="option[]" value="option3"/>
  </div>
  <input type="submit" value="submit"/>
</form>

Javascript

var inputs = document.querySelectorAll('[name="option[]"]')
var radioForCheckboxes = document.getElementById('radio-for-checkboxes')
function checkCheckboxes () 
    var isAtLeastOneServiceSelected = false;
    for(var i = inputs.length-1; i >= 0; --i) 
        if (inputs[i].checked) isAtLeastOneCheckboxSelected = true;
    
    radioForCheckboxes.checked = isAtLeastOneCheckboxSelected

for(var i = inputs.length-1; i >= 0; --i) 
    inputs[i].addEventListener('change', checkCheckboxes)

CSS

.checkboxs-wrapper 
  position: relative;

.checkboxs-wrapper input[name="radio-for-required-checkboxes"] 
    position: absolute;
    margin: 0;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    -webkit-appearance: none;
    pointer-events: none;
    border: none;
    background: none;

https://jsfiddle.net/codus/q6ngpjyc/9/

【讨论】:

这是一个很好的解决方案。奇迹般有效。但是,在 Firefox 中,当使用此单选按钮在所有表单控件上将其设置为必需时,我会在单选按钮框周围看到一个大红色轮廓。除非用户点击提交并执行验证,否则有没有办法将轮廓设置为在无效时不为红色(需要时未选中单选按钮)? 我们可以将radioopacity设置为0,提交时将opacity设置为1,这样我们就可以控制是否出现红色轮廓。 这个解决方案是天才!!在我的情况下,如果我使用visibility: hiddendisplay: none 只是为了避免使可用性有点脏,它就不起作用了。因为屏幕阅读器和其他辅助工具可能会找到隐藏的单选按钮。 为什么不只使用 JavaScript 来实现这一点,而不是 hidden HTML 元素,后者不是?【参考方案8】:

我遇到了同样的问题,我的解决方案是这样的:

HTML:

<form id="processForm.php" action="post">
  <div class="input check_boxes required wish_payment_type">
    <div class="wish_payment_type">
    <span class="checkbox payment-radio">
      <label for="wish_payment_type_1">
        <input class="check_boxes required" id="wish_payment_type_1" name="wish[payment_type][]" type="checkbox" value="1">Foo
      </label>
    </span>
    <span class="checkbox payment-radio">
      <label for="wish_payment_type_2">
        <input class="check_boxes required" id="wish_payment_type_2" name="wish[payment_type][]" type="checkbox" value="2">Bar
      </label>
    </span>
    <span class="checkbox payment-radio">
      <label for="wish_payment_type_3">
        <input class="check_boxes required" id="wish_payment_type_3" name="wish[payment_type][]" type="checkbox" value="3">Buzz
      </label>
          
      <input id='submit' type="submit" value="Submit">
  </div>
</form>

JS:

var verifyPaymentType = function () 
  var checkboxes = $('.wish_payment_type .checkbox');
  var inputs = checkboxes.find('input');
  var first = inputs.first()[0];

  inputs.on('change', function () 
    this.setCustomValidity('');
  );

  first.setCustomValidity(checkboxes.find('input:checked').length === 0 ? 'Choose one' : '');


$('#submit').click(verifyPaymentType);

https://jsfiddle.net/oywLo5z4/

【讨论】:

inputs.on('change', function () this.setCustomValidity(''); ); 没用 jsfiddle.net/d8r2146j【参考方案9】:

你不需要 jQuery。这是一个 vanilla JS 概念证明,使用复选框的父容器 (checkbox-group-required) 上的事件侦听器、复选框元素的 .checked 属性和 Array#some

const validate = el => 
  const checkboxes = el.querySelectorAll('input[type="checkbox"]');
  return [...checkboxes].some(e => e.checked);
;

const formEl = document.querySelector("form");
const statusEl = formEl.querySelector(".status-message");
const checkboxGroupEl = formEl.querySelector(".checkbox-group-required");

checkboxGroupEl.addEventListener("click", e => 
  statusEl.textContent = validate(checkboxGroupEl) ? "valid" : "invalid";
);

formEl.addEventListener("submit", e => 
  e.preventDefault();
  
  if (validate(checkboxGroupEl)) 
    statusEl.textContent = "Form submitted!";
    // Send data from e.target to your backend
  
  else 
    statusEl.textContent = "Error: select at least one checkbox";
  
);
<form>
  <div class="checkbox-group-required">
    <input type="checkbox">
    <input type="checkbox">
    <input type="checkbox">
    <input type="checkbox">
  </div>
  <input type="submit" />
  <div class="status-message"></div>
</form>

如果您要验证多个组,请在每个组上添加一个循环,可选择添加错误消息或 CSS 以指示哪个组未通过验证:

const validate = el => 
  const checkboxes = el.querySelectorAll('input[type="checkbox"]');
  return [...checkboxes].some(e => e.checked);
;
const allValid = els => [...els].every(validate);

const formEl = document.querySelector("form");
const statusEl = formEl.querySelector(".status-message");
const checkboxGroupEls = formEl.querySelectorAll(".checkbox-group-required");

checkboxGroupEls.forEach(el =>
  el.addEventListener("click", e => 
    statusEl.textContent = allValid(checkboxGroupEls) ? "valid" : "invalid";
  )
);

formEl.addEventListener("submit", e => 
  e.preventDefault();
  
  if (allValid(checkboxGroupEls)) 
    statusEl.textContent = "Form submitted!";
  
  else 
    statusEl.textContent = "Error: select at least one checkbox from each group";
  
);
<form>
  <div class="checkbox-group-required">
    <label>
      Group 1:
      <input type="checkbox">
      <input type="checkbox">
      <input type="checkbox">
      <input type="checkbox">
    </label>
  </div>
  <div class="checkbox-group-required">
    <label>
      Group 2:
      <input type="checkbox">
      <input type="checkbox">
      <input type="checkbox">
      <input type="checkbox">
    </label>
  </div>
  <input type="submit" />
  <div class="status-message"></div>
</form>

【讨论】:

如果allValid(checkboxGroupEls)为真,如何继续提交?我有一个 actionaction="includes/action.php" in form 发出 AJAX 请求或仅在验证失败时有条件地在表单上调用 e.preventDefault()【参考方案10】:

我意识到这里有很多解决方案,但我发现它们都没有满足我的所有要求:

无需自定义编码 代码适用于页面加载 不需要自定义类(复选框或其父级) 我需要几个复选框列表来共享相同的 name 以通过他们的 API 提交 Github 问题,并且使用名称 label[] 为许多表单字段(两个复选框列表和一些选择和文本框)分配标签 -诚然,如果他们不使用相同的名字,我可以做到这一点,但我决定尝试一下,它奏效了。

这个的唯一要求是 jQuery。您可以将此与 @ewall 的出色解决方案结合使用,以添加自定义验证错误消息。

/* required checkboxes */
  jQuery(function ($) 
    var $requiredCheckboxes = $("input[type='checkbox'][required]");

    /* init all checkbox lists */
    $requiredCheckboxes.each(function (i, el) 
      //this could easily be changed to suit different parent containers
      var $checkboxList = $(this).closest("div, span, p, ul, td");

      if (!$checkboxList.hasClass("requiredCheckboxList"))
        $checkboxList.addClass("requiredCheckboxList");
    );

    var $requiredCheckboxLists = $(".requiredCheckboxList");

    $requiredCheckboxLists.each(function (i, el) 
      var $checkboxList = $(this);
      $checkboxList.on("change", "input[type='checkbox']", function (e) 
        updateCheckboxesRequired($(this).parents(".requiredCheckboxList"));
      );

      updateCheckboxesRequired($checkboxList);
    );

    function updateCheckboxesRequired($checkboxList) 
      var $chk = $checkboxList.find("input[type='checkbox']").eq(0),
        cblName = $chk.attr("name"),
        cblNameAttr = "[name='" + cblName + "']",
        $checkboxes = $checkboxList.find("input[type='checkbox']" + cblNameAttr);

      if ($checkboxList.find(cblNameAttr + ":checked").length > 0) 
        $checkboxes.prop("required", false);
       else 
        $checkboxes.prop("required", true);
      
    

  );
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<form method="post" action="post.php">
    <div>
        Type of report:
    </div>
    <div>
        <input type="checkbox" id="chkTypeOfReportError" name="label[]" value="Error" required>
        <label for="chkTypeOfReportError">Error</label>

        <input type="checkbox" id="chkTypeOfReportQuestion" name="label[]" value="Question" required>
        <label for="chkTypeOfReportQuestion">Question</label>

        <input type="checkbox" id="chkTypeOfReportFeatureRequest" name="label[]" value="Feature Request" required>
        <label for="chkTypeOfReportFeatureRequest">Feature Request</label>
    </div>

    <div>
        Priority
    </div>
    <div>
        <input type="checkbox" id="chkTypeOfContributionBlog" name="label[]" value="Priority: High" required>
        <label for="chkPriorityHigh">High</label>


        <input type="checkbox" id="chkTypeOfContributionBlog" name="label[]" value="Priority: Medium" required>
        <label for="chkPriorityMedium">Medium</label>


        <input type="checkbox" id="chkTypeOfContributionLow" name="label[]" value="Priority: Low" required>
        <label for="chkPriorityMedium">Low</label>
    </div>
    <div>
        <input type="submit" />
    </div>
</form>

【讨论】:

【参考方案11】:

您好,只需在复选框组之外使用一个文本框。单击任何复选框时,将值放入该文本框。使该文本框为必需且只读。

【讨论】:

【参考方案12】:

验证是否至少选中了一个复选框的非常简单的方法:

function isAtLeastOneChecked(name) 
    let checkboxes = Array.from(document.getElementsByName(name));
    return checkboxes.some(e => e.checked);

然后你可以实现任何你想显示错误的逻辑。

【讨论】:

【参考方案13】:

这是另一个使用 Jquery 的简单技巧! HTML

<form id="hobbieform">
        <div>
            <input type="checkbox" name="hobbies[]">Coding
            <input type="checkbox" name="hobbies[]">Gaming
            <input type="checkbox" name="hobbies[]">Driving
        </div>
</form>

JQuery

$('#hobbieform').on("submit", function (e) 
    var arr = $(this).serialize().toString();
    if(arr.indexOf("hobbies") < 0)
        e.preventDefault();
        alert("You must select at least one hobbie");
    
);

仅此而已.. 这是有效的,因为如果未选中任何复选框,则不会将任何关于复选框组(包括其名称)的内容发布到服务器

【讨论】:

【参考方案14】:

试试:

self.request.get('sports_played', allow_multiple=True)

self.request.POST.getall('sports_played')

更具体地说:

当您从复选框数组中读取数据时,请确保数组具有:

len>0 

在这种情况下:

len(self.request.get('array', allow_multiple=True)) > 0

【讨论】:

您能否详细说明您的答案? 当您从复选框数组中读取数据时,请确保在这种情况下数组的 len>0:len(self.request.get('array', allow_multiple=True)) > 0跨度> 请使用上面评论中的信息编辑您的问题,我很乐意删除反对票。 感谢您编辑您的帖子,但礼貌一点比较合适。 似乎与问题完全无关。正在询问html验证,这里的解决方案是python。这个问题甚至不是询问服务器端验证,而是询问是否有一种方法来验证复选框组以检查是否至少选中了 1 个。

以上是关于对一组复选框使用 HTML5“必需”属性?的主要内容,如果未能解决你的问题,请参考以下文章

如何指示需要一组单选按钮[重复]

在隐藏的单选框/复选框上显示 HTML5 错误消息/验证

如何为一组复选框使用 required 属性? [复制]

当输入填充有 jQuery Validate 插件时,从复选框中删除“必需”

数据验证生成器中的必需复选框

html5如何设置复选框大小