验证模板表单中的复选框列表(不是反应式表单)Angular 2

Posted

技术标签:

【中文标题】验证模板表单中的复选框列表(不是反应式表单)Angular 2【英文标题】:Validation of Checkbox list in Template form(not Reactive forms) Angular 2 【发布时间】:2018-01-23 20:25:15 【问题描述】:

如何验证是否从 Angular 2 模板表单中的复选框列表中选择了至少 1 个复选框?

html 代码。

   <div class="form-control" style="max-height: 300px; overflow: auto">
        <div *ngFor="let item of items" class="checkbox">
            <label for="item.id">
                <input type="checkbox" value="item.id" required id="item.id" [(ngModel)]="item.isSelected" />
                <span class="text-body">item.name</span>
            </label>
        </div>
   </div>
   <div *ngIf="!isAtleastOneItemSelected()" class="alert alert-error">
        Select at least one item
   </div>

组件代码。

public isAtleastOneItemSelected() 
    const selectedItems = this.items.filter((item) => item.isSelected);
    if (selectedItems.length > 0) 
        return true;
     else 
        return false;
    

我已经检查了here 的响应式表单方式。所以,想检查我们如何在模板表单中做到这一点。 使用我上面粘贴的代码,一切正常,但在页面加载时显示错误消息,因为那里没有检查脏或触摸。我被这个问题困住了。

对此的任何帮助将不胜感激。

谢谢。

【问题讨论】:

我也是,我花了一些时间,这似乎是不可能的:( form.valid 总是正确的 你不可能用普通的 ngModel 和自定义验证器来做到这一点。因为你有一个复选框列表,你怎么知道它们是相关的?您必须使用 formGroup 对它们进行分组,然后使用 Reactive Forms 对其进行自定义验证器。工作示例stackblitz.com/edit/… 【参考方案1】:

看看这个,你需要适应:

<div *ngFor="let item of items; let i = index" class="checkbox"> 
        <label for="item.id">
            <input type="checkbox" value="item.id" required id="item.id" [(ngModel)]="item.isSelected" (change)="CheckBoxChanged(i,$event)"/>
            <span class="text-body">item.name</span>
        </label>
 </div>
   <div [hidden]="isAtleastOneItemSelected()" class="alert alert-error">
        Select at least one item
   </div>

把你的检查逻辑放在这里...:

CheckBoxChanged(i,e)
    console.log(i);
    if (e.target.checked)
       console.log("checked");
    else 
       console.log("unchecked");

【讨论】:

如何防止显示初始错误消息,即当控件未变脏或未触摸时? 不过,在初始页面加载时,仍会显示此错误消息,因为不会检查任何关联模型。 你能创建一个 plunkr 吗?【参考方案2】:

我在这里看到了两个可行的选择。我会选择第一个,只是因为我建议避免模板中的任何方法,因为您无法限制触发该方法的时间和频率。尤其是如果您有许多方法以某种方式修改数据的视图,该方法将被触发,即使它与实际的复选框无关。稍后寻找样本。

所以我要做的就是改变

*ngIf="!isAtleastOneItemSelected()"

改为检查变量:

*ngIf="nonChecked"

并在单击复选框时触发某种类型的更改事件 一些方法,例如:

check() 
  const selectedItems = this.items.filter((item) => item.isSelected === true);
  if (selectedItems.length > 0) 
     this.nonChecked = false;
   else 
     this.nonChecked = true;
      

现在只有当复选框被触摸时才会触发。


如果您想保持类似的设置,我看到的另一个选项是将复选框包装在表单组中并观察该组何时被触摸,然后只有在没有检查项目时才显示错误消息。因此,您可以将复选框包装在一个组中:

<div ngModelGroup="checkboxes">
  <!-- .... -->
</div>

然后你可以这样做:

<div *ngIf="!isAtleastOneItemSelected() && f.controls?.checkboxes?.dirty">
  Select at least one item
</div>  

其中f 是表单的名称。但如前所述,这将触发更改检测并在 DOM 中执行任何其他操作。这是此解决方案的示例,我们在 DOM 中只有一个其他字段(请参阅控制台),因此如果您有很多事情要做,我建议您使用第一个解决方案 :) 但无论哪种方式,两者都有效!

http://plnkr.co/edit/VuLNR8H3lasFoK7mRDlG?p=preview

【讨论】:

以上是关于验证模板表单中的复选框列表(不是反应式表单)Angular 2的主要内容,如果未能解决你的问题,请参考以下文章

Angular 反应式表单自定义验证器。仅在选中复选框时启用验证

表单中的复选框验证

django 表单:如何检查模板中的复选框状态

麻烦单元测试角度的反应性表单字段

vue清空表单数据后显示所有列表内容

输入字段表单验证 - 复选框