Skip to content

Commit

Permalink
Support IE Indeterminate checkboxes for "All" option
Browse files Browse the repository at this point in the history
IE handles indeterminate checkboxes "differently", it doesn't fire an
onChange event when a checkbox goes from indeterminate to a determinate
state.

This issue is well documented on the jquery github issue:
jquery/jquery#1698

The generally accepted solution is to use the onClick event instead of the
onChange event. You can see this solution implemented in the google's angular
material design library in their github link here:

angular/components#3145

I applied a similar approach to normalize the events we listen to for the
indeterminate all checkbox and commented why those things are done in the
code so this issue won't regress.
  • Loading branch information
Daniel Latimer committed Apr 24, 2018
1 parent f20b3e4 commit 21dae8c
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 9 deletions.
3 changes: 1 addition & 2 deletions src/lib/treeview.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@
<div *ngIf="config.hasAllCheckBox || config.hasCollapseExpand" class="row row-all">
<div class="col-12">
<div class="form-check">
<input type="checkbox" class="form-check-input" [(ngModel)]="item.checked" (ngModelChange)="onCheckedChange()" [indeterminate]="item.indeterminate"
/>
<input type="checkbox" class="form-check-input" [(ngModel)]="item.checked" [indeterminate]="item.indeterminate" (click)="onCheckedChange()"/>
<label *ngIf="config.hasAllCheckBox" class="form-check-label" (click)="item.checked = !item.checked; onCheckedChange()">
{{i18n.getAllCheckboxText()}}
</label>
Expand Down
32 changes: 25 additions & 7 deletions src/lib/treeview.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,34 @@ export class TreeviewComponent implements OnChanges {
this.updateFilterItems();
}

/**
* IE has an issue where it does not send a change event for when an indeterminate checkbox changes to become determinate.
* To work around this we explicity set it checked if it's indeterminate and we use the onClick event instead of onChange.
*/
onAllCheckedChange() {
const checked = this.allItem.checked;
this.filterItems.forEach(item => {
item.setCheckedRecursive(checked);
if (item instanceof FilterTreeviewItem) {
item.updateRefChecked();
this.standardizeEventOrder(() => {
if (this.allItem.indeterminate) {
this.allItem.checked = true;
}
});

this.raiseSelectedChange();
const checked = this.allItem.checked;
this.filterItems.forEach(item => {
item.setCheckedRecursive(checked);
if (item instanceof FilterTreeviewItem) {
item.updateRefChecked();
}
});

this.raiseSelectedChange();
})
}

/**
* IE performs the onClick event before the onChange event while Chrome and perform it in the other order.
* By pushing the callback onto the event queue it will always be executed immediately after all pending events
*/
standardizeEventOrder(callback) {
setTimeout(callback, 0);
}

onItemCheckedChange(item: TreeviewItem, checked: boolean) {
Expand Down

0 comments on commit 21dae8c

Please sign in to comment.