web-dev-qa-db-fra.com

Comment valider qu'au moins une case doit être cochée?

Je veux faire la validation des cases à cocher ici sans balise de formulaire. Au moins une case à cocher doit être sélectionnée.

<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>

pour les autres champs, je vais mettre obligatoire et faire l'erreur | touché | valide etc. mais comme la case à cocher n'est pas une entrée unique, je ne peux pas mettre obligatoire dans chaque case à cocher car toutes les cases à cocher seront obligatoires à cocher. Alors, comment puis-je faire la validation pour alerter l'utilisateur au moins un devrait être vérifié?

12
user3431310

envisagez de créer une variable FormGroup contenant votre groupe de cases à cocher et de lier la valeur cochée du groupe à un contrôle de formulaire masqué avec un validateur requis.

Supposons que vous ayez trois cases à cocher

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

Step1: définissez FormArray pour vos cases à cocher

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's label)
  checkbox: new FormControl(false)    // checkbox itself
})));

* facile à afficher via ngFor

Step2: créer un formulaire requis masqué pour conserver le statut du groupe de cases à cocher

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

nous nous soucions seulement du statut de validation requis du contrôle caché et ne montrerons pas ce contrôle caché en HTML.

Step3: créer un groupe de formulaires final contient ci-dessous le groupe de cases à cocher et masqué formControl

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

Modèle 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>

renvoyer cette demo .

20
Pengyy

Avec formulaires réactifs , le meilleur, le plus simple et probablement le bon moyen consiste à utiliser un FormGroup qui contient vos cases à cocher groupées et à créer un validateur pour vérifier si au moins une case à cocher est cochée dans ce groupe.

Pour ce faire, il suffit de créer une autre FormGroup à l'intérieur de votre FormGroup existante et de lui associer un validateur:

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...
  });

Et voici le validateur. Je l'ai fait pour que vous puissiez même l'utiliser pour vérifier si au moins X cases sont cochées, par exemple. 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;
  };
}

Dans votre modèle, n'oubliez pas d'ajouter la directive ' formGroupName ' pour envelopper vos cases à cocher. Mais ne vous inquiétez pas, le compilateur vous le rappellera avec un message d'erreur si vous oubliez. Vous pouvez ensuite vérifier si le groupe de cases à cocher est valide de la même manière que vous le faites sur 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>

* Ce modèle est très statique. Bien sûr, vous pouvez le créer dynamiquement en utilisant un tableau supplémentaire contenant les données du formulaire (clé de FormControl, label, requis, etc.) et créer le modèle automatiquement à l'aide de ngFor

J'ai créé un exemple de travail avec lequel vous pouvez jouer: https://stackblitz.com/edit/angular-at-least-one-checkbox-checked

8
Mick

Lors de la validation (par exemple, un événement click), parcourez votre tableau et vérifiez si au moins un élément est vrai.

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");
}
2
Nugu

J'ai eu le même problème et c'est la solution que j'ai finalement utilisée avec Angular 6 FormGroup car j'avais peu de cases à cocher. 

HTMLRemarque: J'utilise un matériau angulaire pour le style, modifiez-le si nécessaire.

<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>

TypeScript

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});
    }
  });
}

En règle générale, abonnez-vous à toutes les modifications apportées au formulaire, puis modifiez les erreurs en fonction des nouvelles valeurs du formulaire.

1
eper

Ajoutez (ngModelChange) = "onChange (officeLIST)" à votre case à cocher et placez le code ci-dessous dans votre fichier .ts.

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

Utilisez la variable isChecked à n’importe quel endroit.

0
shailesh kumar