Как проверить, что нужно выбрать хотя бы один флажок?

Я хочу сделать проверку для флажков здесь без тега формы. Должен быть установлен хотя бы один флажок.

<div *ngFor="let item of officeLIST">
  <div *ngIf=" item.officeID == 1">
    <input #off type="checkbox" id="off" name="off" value="1" [(ngModel)]="item.checked">
    <label>{{item.officename}}</label>
  </div>

  <div *ngIf="item.officeID== 2">
    <input #off type="checkbox" id="off" name="off" value="2" [(ngModel)]="item.checked">
    <label>{{item.officename}}</label>
  </div>

  <div *ngIf="item.officeID== 3">
    <input #off type="checkbox" id="off" name="off" value="3" [(ngModel)]="item.checked">
    <label>{{item.officename}}</label>
  </div>
</div>

для другого поля я поставлю обязательный и сделаю ошибку | коснулся | действительный и т.д., но поскольку флажок не является единичным вводом, я не могу поставить обязательный для каждого флажка, потому что все флажки будут обязательны для проверки. так как мне сделать проверку, чтобы предупредить пользователя, по крайней мере, один должен быть проверен?

Ответ 1

рассмотрите возможность создания FormGroup которая содержит вашу группу флажков и привяжите проверенное значение группы к скрытому контролю формы с требуемым валидатором.

Предположим, что у вас есть три флажка

items = [
  {key: 'item1', text: 'value1'},      // checkbox1 (label: value1)
  {key: 'item2', text: 'value2'},      // checkbox2 (label: value2)
  {key: 'item3', text: 'value3'},      // checkbox3 (label: value3)
];

Шаг 1: определите FormArray для ваших флажков

let checkboxGroup = new FormArray(this.items.map(item => new FormGroup({
  id: new FormControl(item.key),      // id of checkbox(only use its value and won't show in html)
  text: new FormControl(item.text),   // text of checkbox(show its value as checkbox label)
  checkbox: new FormControl(false)    // checkbox itself
})));

* легко показать через ngFor

Шаг 2: создайте скрытый обязательный formControl, чтобы сохранить статус группы флажков

let hiddenControl = new FormControl(this.mapItems(checkboxGroup.value), Validators.required);
// update checkbox group value to hidden formcontrol
checkboxGroup.valueChanges.subscribe((v) => {
  hiddenControl.setValue(this.mapItems(v));
});

мы заботимся только о скрытом элементе управления, необходимом для проверки статуса, и не будем показывать этот скрытый элемент управления в формате HTML.

Шаг 3: создать окончательную группу форм, содержащую ниже флажок группы и скрытый контроль формы

this.form = new FormGroup({
  items: checkboxGroup,
  selectedItems: hiddenControl
});

Шаблон HTML:

<form [formGroup]="form">
  <div [formArrayName]="'items'" [class.invalid]="!form.controls.selectedItems.valid">
    <div *ngFor="let control of form.controls.items.controls; let i = index;" [formGroup]="control">
      <input type="checkbox" formControlName="checkbox" id="{{ control.controls.id.value }}">
      <label attr.for="{{ control.controls.id.value }}">{{ control.controls.text.value }}</label>
    </div>
  </div>
  <div [class.invalid]="!form.controls.selectedItems.valid" *ngIf="!form.controls.selectedItems.valid">
    checkbox group is required!
  </div>
  <hr>
  <pre>{{form.controls.selectedItems.value | json}}</pre>
</form>

см. это демо

Ответ 2

Принятый ответ злоупотребляет вещами, которые они не используют. С реактивными формами лучший, самый простой и, вероятно, правильный способ - это использовать FormGroup, которая содержит ваши сгруппированные флажки и создать валидатор, чтобы проверить, установлен ли хотя бы один (или более) флажок в этой группе.

Для этого просто создайте другую FormGroup внутри существующей FormGroup и присоедините к ней валидатор:

form = new FormGroup({
    // ...more form controls...
    myCheckboxGroup: new FormGroup({
      myCheckbox1: new FormControl(false),
      myCheckbox2: new FormControl(false),
      myCheckbox3: new FormControl(false),
    }, requireCheckboxesToBeCheckedValidator()),
    // ...more form controls...
  });

А вот и валидатор. Я сделал это так, чтобы вы могли даже использовать его, чтобы проверить, установлены ли хотя бы X флажки, например requireCheckboxesToBeCheckedValidator(2):

import { FormGroup, ValidatorFn } from '@angular/forms';

export function requireCheckboxesToBeCheckedValidator(minRequired = 1): ValidatorFn {
  return function validate (formGroup: FormGroup) {
    let checked = 0;

    Object.keys(formGroup.controls).forEach(key => {
      const control = formGroup.controls[key];

      if (control.value === true) {
        checked ++;
      }
    });

    if (checked < minRequired) {
      return {
        requireCheckboxesToBeChecked: true,
      };
    }

    return null;
  };
}

В вашем шаблоне не забудьте добавить директиву formGroupName, чтобы обернуть ваши флажки. Но не волнуйтесь, компилятор напомнит вам с сообщением об ошибке, если вы забудете. Затем вы можете проверить, является ли флажок-группа действительной так же, как и в FormControl:

<ng-container [formGroup]="form">
   <!-- ...more form controls... -->

   <div class="form-group" formGroupName="myCheckboxGroup">
      <div class="custom-control custom-checkbox">
        <input type="checkbox" class="custom-control-input" formControlName="myCheckbox1" id="myCheckbox1">
        <label class="custom-control-label" for="myCheckbox1">Check</label>
      </div>

      <div class="custom-control custom-checkbox">
        <input type="checkbox" class="custom-control-input" formControlName="myCheckbox2" id="myCheckbox2">
        <label class="custom-control-label" for="myCheckbox2">At least</label>
      </div>

      <div class="custom-control custom-checkbox">
        <input type="checkbox" class="custom-control-input" formControlName="myCheckbox3" id="myCheckbox3">
        <label class="custom-control-label" for="myCheckbox3">One</label>
      </div>

      <div class="invalid-feedback" *ngIf="form.controls['myCheckboxGroup'].errors && form.controls['myCheckboxGroup'].errors.requireCheckboxesToBeChecked">At least one checkbox is required to check</div>
    </div>

    <!-- ...more form controls... -->
  </ng-container>

* Этот шаблон очень статичен. Конечно, вы можете создать его динамически, используя дополнительный массив, который содержит данные формы (ключ FormControl, label, required и т.д.) И автоматически создать шаблон с помощью ngFor.

Пожалуйста, не злоупотребляйте скрытым FormControl, как в принятом ответе. FormControl не предназначен для хранения таких данных, как имя, идентификатор, метка, текст справки и т.д. Все это и многое другое должно храниться отдельно, например, с помощью обычного массива объектов. FormControl содержит только входное значение и предоставляет все это классное состояние и функции.

Я создал рабочий пример, с которым вы можете поиграть: https://stackblitz.com/edit/angular-at-least-one-checkbox-checked

Ответ 3

При проверке (т.е. Например, событие click) итерации по вашему массиву и проверьте, является ли хотя бы один элемент истинным.

let isSelected: any = this.officeLIST.filter((item) => item.checked === true);
if(isSelected != null && isSelected.length > 0) {
 //At least one is selected
}else {
 alert("select at least one");
}

Ответ 4

У меня была та же проблема, и это решение я использовал в Angular 6 FormGroup, потому что у меня было несколько флажков.

Примечание HTML: я использую Angular Material для стилей, меняйте их по мере необходимости.

<form [formGroup]="form">
  <mat-checkbox formControlName="checkbox1">First Checkbox</mat-checkbox>
  <mat-checkbox formControlName="checkbox2">Second Checkbox</mat-checkbox>
  <mat-checkbox formControlName="checkbox3">Third Checkbox</mat-checkbox>
</form>

Машинопись

form: FormGroup;

constructor(private formBuilder: FormBuilder){}

ngOnInit(){

  this.form = this.formBuilder.group({
    checkbox1: [''],
    checkbox2: [''],
    checkbox3: [''],
  });

  this.form.setErrors({required: true});
  this.form.valueChanges.subscribe((newValue) => {
    if (newValue.checkbox1 === true || newValue.checkbox2 === true || newValue.checkbox3 === true) {
      this.form.setErrors(null);
    } else {
      this.form.setErrors({required: true});
    }
  });
}

По сути, подпишитесь на любые изменения в форме, а затем измените ошибки по мере необходимости в соответствии с новыми значениями формы.

Ответ 5

Добавьте (ngModelChange) = "onChange (officeLIST)" к своему флажку и введите код в файле.ts.

onChange(items) {
    var found = items.find(function (x) { return x.checked === true; });
    if (found)
      this.isChecked = true;
    else
      this.isChecked = false;
  }

Используйте переменную isChecked в любых местах.

Ответ 6

Вы должны проверять затронутые и грязные условия элемента формы

<form #myForm="ngForm"  *ngIf="active"  (ngSubmit)="onSubmit()">

    <div class="form-group">
        <label for="name">Name</label>
        <input type="text" id="name" class="form-control"
               required name="name" [(ngModel)]="myform.name"
               #name="ngModel" >
        <div *ngIf="name.errors && (name.dirty || name.touched)"
             class="alert alert-danger">
            <div [hidden]="!name.errors.required">
              Name is required
            </div>
        </div>
    </div>

</form>

Вы можете комбинировать предыдущий и мой ответ для обоих сценариев

Ответ 7

Вы можете проверить свой массив "officeList" с помощью функции карты, которую вы можете перебирать по каждому "объекту" в этом массиве и проверять каждый объект "object.checked", и если по крайней мере вы обнаружите, что объект "object.checked" является истинным, значит, это означает по крайней мере, один флажок установлен еще, покажите сообщение об ошибке. Примените эту функцию "onClick()" к кнопке отправки. Надеюсь, поможет. Что-то вроде этого:

Отправить

в component.ts:

onClick(){
    let flag=false;
    this.officeList.map(function(obj){
        if(obj.checked===true){
            flag=true; //set the flag again
        }
    })
    if(flag===false){
        alert('atleast one checkbox should be checked');
        flag=true; //reset the flag again
    }
}