1
votes

Définir indéterminé sur la case à cocher angulaire

J'essaie de définir par programme la valeur des cases à cocher Angular sur false true ou indeterminate . Je comprends que je ne peux pas définir la case à cocher sur la valeur indeterminate mais nous avons accès à [indeterminate] sur l'entrée. Est-il possible de définir les trois états via ngModel d'une manière ou d'une autre?

J'ai le code suivant qui fonctionne un peu, mais j'obtiens une erreur ExpressionChangedAfterItHasBeenCheckedError .

HTML

checkedLabels(label): boolean {
    const index = this.selectedLabels.indexOf(label.objectId);
    this. indeterminateState = false;
    if (!this.selectedClients.length) {
      return false;
    }
    if (this.countInArray(this.selectedLabels, label.objectId) === this.selectedClients.length) {
      return true;
    }
    if (index >= 0) {
      this. indeterminateState = true;
    }
  }

countInArray(array, value) {
  return array.reduce((n, x) => n + (x === value), 0);
}

TS

<div *ngFor="let label of ClientLabels | async">
  <label for="{{label.objectId}}">{{label.labelName}}</label>
  <input id="{{label.objectId}}" type="checkbox" name="group" [indeterminate]="checkedLabels()"
      [checked]="checkedLabels(label)" (change)="toggleSelectedLabels(label)" />
</div>

Ici, le cas d'utilisation est similaire à celui des étiquettes dans Gmail, sauf que les clients sont utilisés à la place d'un e-mail. Si tous les e-mails ont le même libellé, ils apparaissent comme cochés, mais si tous ne partagent pas le libellé, il affichera un indéterminé qui peut être parcouru à travers les trois états (vrai, faux, indéterminé).

Q1. Comment puis-je parcourir ces trois états de la même manière qu'avec gmail?

Q2. Pourquoi est-ce que j'obtiens le ExpressionChangedAfterItHasBeenCheckedError avec la configuration actuelle?

Voici un Stackblitz de la progression actuelle https://stackblitz.com/edit/ angular-3bbutx

 Exemple de case à cocher Gmail à trois états


2 commentaires

Veuillez remplacer intermédiaire par indeterminate dans votre question.


merci @ConnorsFan


3 Réponses :


6
votes

Pour rendre une case à cocher indéterminée, vous pouvez utiliser une directive

  click(cliente: any) {
    let indeterminated=(!cliente.checked && !cliente.indeterminated) ? true : false;
    let checked=(!cliente.checked && cliente.indeterminated)?true:false
    cliente.indeterminated = indeterminated;
    cliente.checked=checked;
  }

Ensuite, votre case à cocher peut être comme

<input class="pull-left" type="checkbox" 
     [indeterminate]="client.indeterminated" 
     [checked]="client.checked" (click)="click(client)"/>

import { Directive, ElementRef,Input } from '@angular/core';

@Directive({ selector: '[indeterminate]' })
export class IndeterminateDirective {
   @Input() 
   set indeterminate(value)
   {
     this.elem.nativeElement.indeterminate=value;
   }
    constructor(private elem: ElementRef) {
    }
}

Voyant que vous avez deux variables "cochées" et "indéterminées", vous pouvez faire un cycle comme vous le souhaitez


4 commentaires

Pouvons-nous ajouter facilement du faux? Donc, c'est cyclé entre les trois?


stackblitz.com/edit/… . Si vous cliquez sur rendre le cycle: indéterminé - coché - non coché. REMARQUE: lorsque indéterminé est égal à vrai, n'importez pas si est coché ou non.


@Eliseo le a déjà un attribut indeterminate , donc si vous supprimez la directive, cela fonctionne toujours bien.


@DiegoOrtiz, pouvez-vous faire un stackblitz? Je ne peux pas imaginer comment faire sans directive



0
votes

Oui, vous pouvez utiliser [indeterminate] = "condition" (sans aucune directive). Vous ne pouvez pas faire indeterminate = "{{condition}}" . La différence est que [...] définit la propriété de l'élément, alors que sans crochets, vous définissez l'attribut. L'élément HTMLInput a la propriété indeterminate , mais n'a pas un tel attribut.

Pour utiliser ngModel ou FormControl, qui contient simultanément les états checked et indeterminate , vous devez créer une directive personnalisée ou / et une logique supplémentaire dans votre composant principal ( pour référence, voir la réponse de @Eliseo).

Q1. Comment puis-je parcourir ces trois états de la même manière qu'avec Gmail?

Gérer les clics, changer l'état de la paire "cochée" et "indéterminée" en cycle. Exemple avec jQuery .

Q2. Pourquoi est-ce que j'obtiens l'erreur ExpressionChangedAfterItHasBeenCheckedError avec la configuration actuelle?

Vous avez un effet secondaire dans la méthode checkedLabels , qui change l'état du composant, à chaque fois qu'Angular vérifie la valeur de l'expression [indeterminate] = "checkedLabels ()" .


0 commentaires

0
votes

Après une longue recherche, je l'ai fait comme ça:

Dans le fichier html:

      input[type=checkbox]:checked + b:before {
           content: "\2713";
           font-family: ux-icons;

      }

  input[type=checkbox]:indeterminate + b:before {
       content: "\f067";
       font: 14px/1 DXIcons;
  }

et dans le fichier css:

<input #checkboxes
       type="checkbox"
       [checked]="some_condition"
       [indeterminate]="!some_condition && some_another_condition">
<b class="checkbox-container"></b>


0 commentaires