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
3 Réponses :
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)"/>
où
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
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
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 ()" .
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>
Veuillez remplacer
intermédiaireparindeterminatedans votre question.merci @ConnorsFan