Set indeterminate on Angular checkbox

 ̄綄美尐妖づ 提交于 2020-06-09 05:01:05

问题


I'm trying to programatically set the value of Angular checkboxes to either, false true or indeterminate. I understand that I cannot set the checkbox to the value indeterminate however we do have access to [indeterminate] on the input. Is it possible to set all three states via ngModel somehow?

I have the following code which kinda works, however I am getting a ExpressionChangedAfterItHasBeenCheckedError error.

HTML

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

TS

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

Here the use case is similar to that of labels in Gmail, except clients are used in the place of an email. If all of the emails have the same label then they show as checked, however if not all of them share the label then it will show an indeterminate which can be cycled through the three states (true, false, indeterminate).

Q1. How can I cycle through these three state in the same way as you can with gmail?

Q2. Why am I getting the ExpressionChangedAfterItHasBeenCheckedError with the current setup?

Here is a Stackblitz of current progress https://stackblitz.com/edit/angular-3bbutx


回答1:


To make a checkbox indeterminated, you can use a directive

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

Then you're checkbox can be like

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

where

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

See that you have two variables "checked" and "indeterminated", you can make a cycle as you want



来源:https://stackoverflow.com/questions/54075014/set-indeterminate-on-angular-checkbox

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!