@progress/kendo-angular-dropdowns 5.4.0-dev.202107201315 → 5.5.0-dev.202110291622

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/cdn/js/kendo-angular-dropdowns.js +2 -2
  2. package/dist/cdn/main.js +1 -1
  3. package/dist/es/common/filtering/filter.directive.js +1 -0
  4. package/dist/es/common/localization/messages.js +4 -0
  5. package/dist/es/common/shared.module.js +3 -1
  6. package/dist/es/dropdowntrees/checked-state/base-check.directive.js +54 -0
  7. package/dist/es/dropdowntrees/checked-state/check-all.directive.js +181 -0
  8. package/dist/es/dropdowntrees/checked-state/check.directive.js +15 -36
  9. package/dist/es/dropdowntrees/dropdowntree.component.js +1 -2
  10. package/dist/es/dropdowntrees/multiselecttree.component.js +58 -13
  11. package/dist/es/index.js +2 -0
  12. package/dist/es/package-metadata.js +1 -1
  13. package/dist/es2015/common/filtering/filter.directive.d.ts +1 -0
  14. package/dist/es2015/common/filtering/filter.directive.js +1 -0
  15. package/dist/es2015/common/localization/messages.d.ts +4 -0
  16. package/dist/es2015/common/localization/messages.js +4 -0
  17. package/dist/es2015/common/shared.module.js +3 -1
  18. package/dist/es2015/dropdowntrees/checked-state/base-check.directive.d.ts +32 -0
  19. package/dist/es2015/dropdowntrees/checked-state/base-check.directive.js +48 -0
  20. package/dist/es2015/dropdowntrees/checked-state/check-all.directive.d.ts +53 -0
  21. package/dist/es2015/dropdowntrees/checked-state/check-all.directive.js +161 -0
  22. package/dist/es2015/dropdowntrees/checked-state/check.directive.d.ts +3 -5
  23. package/dist/es2015/dropdowntrees/checked-state/check.directive.js +5 -26
  24. package/dist/es2015/dropdowntrees/dropdowntree.component.js +1 -2
  25. package/dist/es2015/dropdowntrees/multiselecttree.component.d.ts +14 -0
  26. package/dist/es2015/dropdowntrees/multiselecttree.component.js +82 -15
  27. package/dist/es2015/index.d.ts +2 -0
  28. package/dist/es2015/index.js +2 -0
  29. package/dist/es2015/index.metadata.json +1 -1
  30. package/dist/es2015/package-metadata.js +1 -1
  31. package/dist/fesm2015/index.js +289 -45
  32. package/dist/fesm5/index.js +300 -53
  33. package/dist/npm/common/filtering/filter.directive.js +1 -0
  34. package/dist/npm/common/localization/messages.js +4 -0
  35. package/dist/npm/common/shared.module.js +3 -1
  36. package/dist/npm/dropdowntrees/checked-state/base-check.directive.js +56 -0
  37. package/dist/npm/dropdowntrees/checked-state/check-all.directive.js +183 -0
  38. package/dist/npm/dropdowntrees/checked-state/check.directive.js +14 -35
  39. package/dist/npm/dropdowntrees/dropdowntree.component.js +1 -2
  40. package/dist/npm/dropdowntrees/multiselecttree.component.js +58 -13
  41. package/dist/npm/index.js +4 -0
  42. package/dist/npm/package-metadata.js +1 -1
  43. package/dist/systemjs/kendo-angular-dropdowns.js +1 -1
  44. package/package.json +5 -5
@@ -0,0 +1,32 @@
1
+ /**-----------------------------------------------------------------------------------------
2
+ * Copyright © 2021 Progress Software Corporation. All rights reserved.
3
+ * Licensed under commercial license. See LICENSE.md in the project root for more information
4
+ *-------------------------------------------------------------------------------------------*/
5
+ import { TreeItem } from '@progress/kendo-angular-treeview';
6
+ import { CheckedItem } from './checked-item';
7
+ /**
8
+ * @hidden
9
+ *
10
+ * A directive which manages the in-memory checked state of the MultiSelectTree nodes.
11
+ */
12
+ export declare abstract class BaseCheckDirective {
13
+ /**
14
+ * The item key/keys by which the data items will be compared.
15
+ */
16
+ abstract valueField: string | string[];
17
+ /**
18
+ * Defines the collection that will store the full checked items.
19
+ */
20
+ abstract checkedItems: CheckedItem[];
21
+ /**
22
+ * Holds a Set with just the checked item keys.
23
+ *
24
+ * Should be updated each time the `checkedItems` value or content is changed.
25
+ * Can be used for efficient look-up of whether an item is checked or not (O(1) access time).
26
+ */
27
+ abstract checkedKeys: Set<any>;
28
+ protected addItem(item: TreeItem): void;
29
+ protected removeItem(item: TreeItem): void;
30
+ protected isItemChecked(item: CheckedItem): boolean;
31
+ protected updateItems(): void;
32
+ }
@@ -0,0 +1,48 @@
1
+ /**-----------------------------------------------------------------------------------------
2
+ * Copyright © 2021 Progress Software Corporation. All rights reserved.
3
+ * Licensed under commercial license. See LICENSE.md in the project root for more information
4
+ *-------------------------------------------------------------------------------------------*/
5
+ import * as tslib_1 from "tslib";
6
+ import { Input } from '@angular/core';
7
+ import { getHierarchicalItemLevel, valueFrom } from '../../common/util';
8
+ /**
9
+ * @hidden
10
+ *
11
+ * A directive which manages the in-memory checked state of the MultiSelectTree nodes.
12
+ */
13
+ export class BaseCheckDirective {
14
+ addItem(item) {
15
+ if (this.isItemChecked(item)) {
16
+ return;
17
+ }
18
+ const level = getHierarchicalItemLevel(item.index);
19
+ const candidate = Object.assign({}, item, { level });
20
+ this.checkedItems.push(candidate);
21
+ this.checkedKeys.add(valueFrom(candidate, this.valueField));
22
+ }
23
+ removeItem(item) {
24
+ if (!this.isItemChecked(item)) {
25
+ return;
26
+ }
27
+ const level = getHierarchicalItemLevel(item.index);
28
+ const candidate = Object.assign({}, item, { level });
29
+ this.checkedItems = this.checkedItems
30
+ .filter(item => valueFrom(item, this.valueField) !== valueFrom(candidate, this.valueField));
31
+ this.checkedKeys.delete(valueFrom(candidate, this.valueField));
32
+ }
33
+ isItemChecked(item) {
34
+ return this.checkedKeys.has(valueFrom(item, this.valueField));
35
+ }
36
+ updateItems() {
37
+ this.checkedItems = this.checkedItems || [];
38
+ this.checkedKeys = new Set(this.checkedItems.map(item => valueFrom(item, this.valueField)));
39
+ }
40
+ }
41
+ tslib_1.__decorate([
42
+ Input(),
43
+ tslib_1.__metadata("design:type", Object)
44
+ ], BaseCheckDirective.prototype, "valueField", void 0);
45
+ tslib_1.__decorate([
46
+ Input(),
47
+ tslib_1.__metadata("design:type", Array)
48
+ ], BaseCheckDirective.prototype, "checkedItems", void 0);
@@ -0,0 +1,53 @@
1
+ /**-----------------------------------------------------------------------------------------
2
+ * Copyright © 2021 Progress Software Corporation. All rights reserved.
3
+ * Licensed under commercial license. See LICENSE.md in the project root for more information
4
+ *-------------------------------------------------------------------------------------------*/
5
+ import { ChangeDetectorRef, ElementRef, EventEmitter, NgZone, OnChanges, OnInit, Renderer2, SimpleChanges } from '@angular/core';
6
+ import { TreeViewComponent } from '@progress/kendo-angular-treeview';
7
+ import { BaseCheckDirective } from './base-check.directive';
8
+ import { CheckedItem } from './checked-item';
9
+ /**
10
+ * @hidden
11
+ *
12
+ * A directive which manages the in-memory checked state of the MultiSelectTree nodes.
13
+ */
14
+ export declare class CheckAllDirective extends BaseCheckDirective implements OnChanges, OnInit {
15
+ private element;
16
+ private zone;
17
+ cdr: ChangeDetectorRef;
18
+ renderer: Renderer2;
19
+ lastAction: 'check' | 'uncheck';
20
+ treeview: TreeViewComponent;
21
+ /**
22
+ * Defines the collection that will store the full checked items.
23
+ */
24
+ checkedItems: CheckedItem[];
25
+ /**
26
+ * The item key/keys by which the data items will be compared.
27
+ */
28
+ valueField: string | string[];
29
+ focused: boolean;
30
+ /**
31
+ * Fires when the `checkedItems` collection was updated.
32
+ */
33
+ checkedItemsChange: EventEmitter<CheckedItem[]>;
34
+ /**
35
+ * Holds a Set with just the checked item keys.
36
+ *
37
+ * Should be updated each time the `checkedItems` value or content is changed.
38
+ * Can be used for efficient look-up of whether an item is checked or not (O(1) access time).
39
+ */
40
+ checkedKeys: Set<any>;
41
+ private currentCheckedState;
42
+ private currentIndeterminateState;
43
+ handleChange(event: any): void;
44
+ readonly isIndeterminate: boolean;
45
+ readonly isChecked: boolean;
46
+ constructor(element: ElementRef, zone: NgZone, cdr: ChangeDetectorRef, renderer: Renderer2);
47
+ ngOnChanges(changes: SimpleChanges): void;
48
+ ngOnInit(): void;
49
+ private nextTick;
50
+ private checkNode;
51
+ private allChecked;
52
+ private someChecked;
53
+ }
@@ -0,0 +1,161 @@
1
+ /**-----------------------------------------------------------------------------------------
2
+ * Copyright © 2021 Progress Software Corporation. All rights reserved.
3
+ * Licensed under commercial license. See LICENSE.md in the project root for more information
4
+ *-------------------------------------------------------------------------------------------*/
5
+ import * as tslib_1 from "tslib";
6
+ import { ChangeDetectorRef, Directive, ElementRef, EventEmitter, HostListener, Input, NgZone, Output, Renderer2 } from '@angular/core';
7
+ import { TreeViewComponent } from '@progress/kendo-angular-treeview';
8
+ import { fetchDescendentNodes, isPresent } from '../../common/util';
9
+ import { BaseCheckDirective } from './base-check.directive';
10
+ /**
11
+ * @hidden
12
+ *
13
+ * A directive which manages the in-memory checked state of the MultiSelectTree nodes.
14
+ */
15
+ let CheckAllDirective = class CheckAllDirective extends BaseCheckDirective {
16
+ constructor(element, zone, cdr, renderer) {
17
+ super();
18
+ this.element = element;
19
+ this.zone = zone;
20
+ this.cdr = cdr;
21
+ this.renderer = renderer;
22
+ /**
23
+ * Fires when the `checkedItems` collection was updated.
24
+ */
25
+ this.checkedItemsChange = new EventEmitter();
26
+ /**
27
+ * Holds a Set with just the checked item keys.
28
+ *
29
+ * Should be updated each time the `checkedItems` value or content is changed.
30
+ * Can be used for efficient look-up of whether an item is checked or not (O(1) access time).
31
+ */
32
+ this.checkedKeys = new Set();
33
+ }
34
+ handleChange(event) {
35
+ // Need to store the current checkbox state at the moment of click
36
+ this.currentCheckedState = event.checked;
37
+ this.currentIndeterminateState = this.isIndeterminate;
38
+ this.treeview.nodes.map((_value, index) => {
39
+ const itemIndex = String(index);
40
+ const itemLookup = this.treeview.itemLookup(itemIndex);
41
+ this.checkNode(itemLookup);
42
+ });
43
+ this.checkedItemsChange.emit(this.checkedItems.slice());
44
+ }
45
+ get isIndeterminate() {
46
+ const isIndeterminate = this.treeview.nodes.some((_node, index) => {
47
+ const itemIndex = String(index);
48
+ const itemLookup = this.treeview.itemLookup(itemIndex);
49
+ return this.someChecked(itemLookup);
50
+ });
51
+ return this.isChecked ? false : isIndeterminate;
52
+ }
53
+ get isChecked() {
54
+ const isChecked = this.treeview.nodes.every((_node, index) => {
55
+ const itemIndex = String(index);
56
+ const itemLookup = this.treeview.itemLookup(itemIndex);
57
+ return this.allChecked(itemLookup);
58
+ });
59
+ return isChecked;
60
+ }
61
+ ngOnChanges(changes) {
62
+ if (isPresent(changes.checkedItems)) {
63
+ this.updateItems();
64
+ this.renderer.setProperty(this.element.nativeElement, 'checked', this.isChecked);
65
+ this.renderer.setProperty(this.element.nativeElement, 'indeterminate', this.isIndeterminate);
66
+ }
67
+ }
68
+ ngOnInit() {
69
+ if (this.focused) {
70
+ this.nextTick(() => this.element.nativeElement.focus());
71
+ }
72
+ }
73
+ nextTick(fn) {
74
+ this.zone.runOutsideAngular(() => setTimeout(fn));
75
+ }
76
+ checkNode(itemLookup) {
77
+ if (this.treeview.isDisabled(itemLookup.item.dataItem, itemLookup.item.index)) {
78
+ return;
79
+ }
80
+ const pendingCheck = [];
81
+ const filter = (item) => this.treeview.isVisible(item.dataItem, item.index) &&
82
+ !this.treeview.isDisabled(item.dataItem, item.index);
83
+ pendingCheck.push(itemLookup.item);
84
+ fetchDescendentNodes(itemLookup, filter)
85
+ .forEach(lookup => pendingCheck.push(lookup.item));
86
+ pendingCheck.forEach(item => {
87
+ if (this.currentIndeterminateState) {
88
+ this.lastAction === 'check' ?
89
+ this.addItem(item) :
90
+ this.removeItem(item);
91
+ return;
92
+ }
93
+ this.currentCheckedState ?
94
+ this.addItem(item) :
95
+ this.removeItem(item);
96
+ });
97
+ }
98
+ allChecked(lookup) {
99
+ const children = lookup && lookup.children;
100
+ if (!Array.isArray(children)) {
101
+ return;
102
+ }
103
+ const childrenChecked = children.every(child => {
104
+ if (child.children.length) {
105
+ return this.isItemChecked(child.item) && this.allChecked(child);
106
+ }
107
+ return this.isItemChecked(child.item);
108
+ });
109
+ return childrenChecked && this.isItemChecked(lookup.item);
110
+ }
111
+ someChecked(lookup) {
112
+ const children = lookup && lookup.children;
113
+ if (!Array.isArray(children)) {
114
+ return;
115
+ }
116
+ const childrenChecked = children.some(child => {
117
+ if (child.children.length) {
118
+ return this.isItemChecked(child.item) || this.someChecked(child);
119
+ }
120
+ return this.isItemChecked(child.item);
121
+ });
122
+ return childrenChecked || this.isItemChecked(lookup.item);
123
+ }
124
+ };
125
+ tslib_1.__decorate([
126
+ Input(),
127
+ tslib_1.__metadata("design:type", String)
128
+ ], CheckAllDirective.prototype, "lastAction", void 0);
129
+ tslib_1.__decorate([
130
+ Input(),
131
+ tslib_1.__metadata("design:type", TreeViewComponent)
132
+ ], CheckAllDirective.prototype, "treeview", void 0);
133
+ tslib_1.__decorate([
134
+ Input(),
135
+ tslib_1.__metadata("design:type", Array)
136
+ ], CheckAllDirective.prototype, "checkedItems", void 0);
137
+ tslib_1.__decorate([
138
+ Input(),
139
+ tslib_1.__metadata("design:type", Object)
140
+ ], CheckAllDirective.prototype, "valueField", void 0);
141
+ tslib_1.__decorate([
142
+ Input('checkAll'),
143
+ tslib_1.__metadata("design:type", Boolean)
144
+ ], CheckAllDirective.prototype, "focused", void 0);
145
+ tslib_1.__decorate([
146
+ Output(),
147
+ tslib_1.__metadata("design:type", EventEmitter)
148
+ ], CheckAllDirective.prototype, "checkedItemsChange", void 0);
149
+ tslib_1.__decorate([
150
+ HostListener('change', ['$event.target']),
151
+ tslib_1.__metadata("design:type", Function),
152
+ tslib_1.__metadata("design:paramtypes", [Object]),
153
+ tslib_1.__metadata("design:returntype", void 0)
154
+ ], CheckAllDirective.prototype, "handleChange", null);
155
+ CheckAllDirective = tslib_1.__decorate([
156
+ Directive({
157
+ selector: '[checkAll]' // tslint:disable-line
158
+ }),
159
+ tslib_1.__metadata("design:paramtypes", [ElementRef, NgZone, ChangeDetectorRef, Renderer2])
160
+ ], CheckAllDirective);
161
+ export { CheckAllDirective };
@@ -6,12 +6,13 @@ import { EventEmitter, OnDestroy, OnChanges, SimpleChanges } from '@angular/core
6
6
  import { TreeViewComponent } from '@progress/kendo-angular-treeview';
7
7
  import { CheckedItem } from './checked-item';
8
8
  import { MultiSelectTreeCheckableSettings } from './checkable-settings';
9
+ import { BaseCheckDirective } from './base-check.directive';
9
10
  /**
10
11
  * @hidden
11
12
  *
12
13
  * A directive which manages the in-memory checked state of the MultiSelectTree nodes.
13
14
  */
14
- export declare class CheckDirective implements OnChanges, OnDestroy {
15
+ export declare class CheckDirective extends BaseCheckDirective implements OnChanges, OnDestroy {
15
16
  private treeView;
16
17
  /**
17
18
  * Specifies whether items should be checked on click,
@@ -37,7 +38,7 @@ export declare class CheckDirective implements OnChanges, OnDestroy {
37
38
  * Should be updated each time the `checkedItems` value or content is changed.
38
39
  * Can be used for efficient look-up of whether an item is checked or not (O(1) access time).
39
40
  */
40
- private checkedKeys;
41
+ checkedKeys: Set<any>;
41
42
  private subscriptions;
42
43
  private clickSubscription;
43
44
  constructor(treeView: TreeViewComponent);
@@ -49,8 +50,5 @@ export declare class CheckDirective implements OnChanges, OnDestroy {
49
50
  private unsubscribeClick;
50
51
  private checkNode;
51
52
  private checkParents;
52
- private addItem;
53
- private removeItem;
54
- private isItemChecked;
55
53
  private isItemIndeterminate;
56
54
  }
@@ -7,14 +7,16 @@ import { Directive, EventEmitter, Input, Output } from '@angular/core';
7
7
  import { TreeViewComponent } from '@progress/kendo-angular-treeview';
8
8
  import { Subscription } from 'rxjs';
9
9
  import { filter } from 'rxjs/operators';
10
- import { fetchDescendentNodes, getHierarchicalItemLevel, isPresent, valueFrom } from '../../common/util';
10
+ import { fetchDescendentNodes, isPresent } from '../../common/util';
11
+ import { BaseCheckDirective } from './base-check.directive';
11
12
  /**
12
13
  * @hidden
13
14
  *
14
15
  * A directive which manages the in-memory checked state of the MultiSelectTree nodes.
15
16
  */
16
- let CheckDirective = class CheckDirective {
17
+ let CheckDirective = class CheckDirective extends BaseCheckDirective {
17
18
  constructor(treeView) {
19
+ super();
18
20
  this.treeView = treeView;
19
21
  /**
20
22
  * Fires when the `checkedItems` collection was updated.
@@ -37,8 +39,7 @@ let CheckDirective = class CheckDirective {
37
39
  this.toggleCheckOnClick();
38
40
  }
39
41
  if (isPresent(changes.checkedItems)) {
40
- this.checkedItems = this.checkedItems || [];
41
- this.checkedKeys = new Set(this.checkedItems.map(item => valueFrom(item, this.valueField)));
42
+ this.updateItems();
42
43
  }
43
44
  }
44
45
  ngOnDestroy() {
@@ -118,28 +119,6 @@ let CheckDirective = class CheckDirective {
118
119
  currentParent = currentParent.parent;
119
120
  }
120
121
  }
121
- addItem(item) {
122
- if (this.isItemChecked(item)) {
123
- return;
124
- }
125
- const level = getHierarchicalItemLevel(item.index);
126
- const candidate = Object.assign({}, item, { level });
127
- this.checkedItems.push(candidate);
128
- this.checkedKeys.add(valueFrom(candidate, this.valueField));
129
- }
130
- removeItem(item) {
131
- if (!this.isItemChecked(item)) {
132
- return;
133
- }
134
- const level = getHierarchicalItemLevel(item.index);
135
- const candidate = Object.assign({}, item, { level });
136
- this.checkedItems = this.checkedItems
137
- .filter(item => valueFrom(item, this.valueField) !== valueFrom(candidate, this.valueField));
138
- this.checkedKeys.delete(valueFrom(candidate, this.valueField));
139
- }
140
- isItemChecked(item) {
141
- return this.checkedKeys.has(valueFrom(item, this.valueField));
142
- }
143
122
  isItemIndeterminate(lookup) {
144
123
  const children = lookup.children;
145
124
  if (!Array.isArray(children) || children.length === 0) {
@@ -552,8 +552,8 @@ let DropDownTreeComponent = DropDownTreeComponent_1 = class DropDownTreeComponen
552
552
  dataItem;
553
553
  const shouldUpdateValue = newValue !== this.value;
554
554
  if (shouldUpdateValue) {
555
- this.dataItem = dataItem;
556
555
  this.value = newValue;
556
+ this.dataItem = dataItem;
557
557
  this.emitValueChange(this.value);
558
558
  }
559
559
  this.togglePopup(false);
@@ -753,7 +753,6 @@ let DropDownTreeComponent = DropDownTreeComponent_1 = class DropDownTreeComponen
753
753
  }
754
754
  clearState() {
755
755
  this.text = undefined;
756
- this.valueDepth = undefined;
757
756
  this.selectedKeys = [];
758
757
  }
759
758
  subscribeEvents() {
@@ -46,6 +46,7 @@ export declare class MultiSelectTreeComponent implements OnInit, OnDestroy, OnCh
46
46
  container: ViewContainerRef;
47
47
  treeview: TreeViewComponent;
48
48
  private filterInput;
49
+ private checkAllInput;
49
50
  /**
50
51
  * Specifies the [`tabindex`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex) of the component.
51
52
  */
@@ -160,6 +161,12 @@ export declare class MultiSelectTreeComponent implements OnInit, OnDestroy, OnCh
160
161
  * @default false
161
162
  */
162
163
  filterable: boolean;
164
+ /**
165
+ * If `checkАll` is set to `true` and the checkboxes are enabled, a tri-state checkbox appears above the embedded treeview.
166
+ * Clicking the checkbox checks or unchecks all enabled items of the treeview that are loaded.
167
+ * @default false
168
+ */
169
+ checkAll: boolean;
163
170
  /**
164
171
  * A function which determines if a specific node has child nodes.
165
172
  */
@@ -302,6 +309,8 @@ export declare class MultiSelectTreeComponent implements OnInit, OnDestroy, OnCh
302
309
  private readonly isTagFocused;
303
310
  private readonly isTreeViewActive;
304
311
  private readonly isWrapperActive;
312
+ private readonly isFilterActive;
313
+ private readonly isCheckAllActive;
305
314
  /**
306
315
  * @hidden
307
316
  */
@@ -419,6 +428,7 @@ export declare class MultiSelectTreeComponent implements OnInit, OnDestroy, OnCh
419
428
  * @hidden
420
429
  */
421
430
  messageFor(key: string): string;
431
+ lastAction: 'check' | 'uncheck';
422
432
  /**
423
433
  * @hidden
424
434
  */
@@ -458,6 +468,10 @@ export declare class MultiSelectTreeComponent implements OnInit, OnDestroy, OnCh
458
468
  * @hidden
459
469
  */
460
470
  handleFilterInputChange(term: string): void;
471
+ /**
472
+ * @hidden
473
+ */
474
+ toggleCheckAll(): void;
461
475
  protected onTouchedCallback: Function;
462
476
  protected onChangeCallback: Function;
463
477
  protected verifySettings(): void;
@@ -107,6 +107,12 @@ let MultiSelectTreeComponent = MultiSelectTreeComponent_1 = class MultiSelectTre
107
107
  * @default false
108
108
  */
109
109
  this.filterable = false;
110
+ /**
111
+ * If `checkАll` is set to `true` and the checkboxes are enabled, a tri-state checkbox appears above the embedded treeview.
112
+ * Clicking the checkbox checks or unchecks all enabled items of the treeview that are loaded.
113
+ * @default false
114
+ */
115
+ this.checkAll = false;
110
116
  /**
111
117
  * A function which determines if a specific node has child nodes.
112
118
  */
@@ -210,6 +216,7 @@ let MultiSelectTreeComponent = MultiSelectTreeComponent_1 = class MultiSelectTre
210
216
  this._checkableSettings = DEFAULT_CHECKABLE_SETTINGS;
211
217
  this._isFocused = false;
212
218
  this.subscriptions = [];
219
+ this.lastAction = 'check';
213
220
  this.onTouchedCallback = noop;
214
221
  this.onChangeCallback = noop;
215
222
  this.direction = localization.rtl ? 'rtl' : 'ltr';
@@ -219,7 +226,7 @@ let MultiSelectTreeComponent = MultiSelectTreeComponent_1 = class MultiSelectTre
219
226
  this._treeview = treeview;
220
227
  if (treeview) {
221
228
  // If filtering is enabled, focus the TreeView on mobile devices instead of the filter input
222
- if (this.isFocused && !this.filterable || this.touchEnabled) {
229
+ if (this.isFocused && !this.filterable && !this.checkAll || this.touchEnabled) {
223
230
  treeview.focus();
224
231
  }
225
232
  /**
@@ -450,6 +457,12 @@ let MultiSelectTreeComponent = MultiSelectTreeComponent_1 = class MultiSelectTre
450
457
  get isWrapperActive() {
451
458
  return document.activeElement === this.wrapper.nativeElement;
452
459
  }
460
+ get isFilterActive() {
461
+ return this.filterInput && document.activeElement === this.filterInput.nativeElement;
462
+ }
463
+ get isCheckAllActive() {
464
+ return this.checkAllInput && document.activeElement === this.checkAllInput.nativeElement;
465
+ }
453
466
  ngOnInit() {
454
467
  this.renderer.removeAttribute(this.hostElement.nativeElement, 'tabindex');
455
468
  this.renderer.setAttribute(this.wrapper.nativeElement, 'aria-expanded', String(this.isOpen));
@@ -666,6 +679,7 @@ let MultiSelectTreeComponent = MultiSelectTreeComponent_1 = class MultiSelectTre
666
679
  */
667
680
  handleCheckedItemsChange(items) {
668
681
  this.valueDepth = items.map(item => item.level);
682
+ this.lastAction = items.length > this.dataItems.length ? 'check' : 'uncheck';
669
683
  this.dataItems = items.slice();
670
684
  this.updateValue(this.dataItems);
671
685
  }
@@ -754,6 +768,13 @@ let MultiSelectTreeComponent = MultiSelectTreeComponent_1 = class MultiSelectTre
754
768
  this.filterChange.next(term);
755
769
  this.allNodesHidden = this.nodes.every((node, index) => !this.isVisible(node, String(index)));
756
770
  }
771
+ /**
772
+ * @hidden
773
+ */
774
+ toggleCheckAll() {
775
+ this.checkAllInput.nativeElement.focus();
776
+ this.checkAllInput.nativeElement.click();
777
+ }
757
778
  verifySettings() {
758
779
  if (!isDevMode()) {
759
780
  return;
@@ -876,17 +897,20 @@ let MultiSelectTreeComponent = MultiSelectTreeComponent_1 = class MultiSelectTre
876
897
  return;
877
898
  }
878
899
  const isFirstNodeActive = this.treeview['navigationService']['activeIndex'] === '0';
879
- if (this.filterable) {
880
- const isFilterActive = this.filterInput.nativeElement === document.activeElement;
881
- if (isFilterActive) {
882
- this.focus();
883
- }
884
- else if (!isFilterActive && isFirstNodeActive) {
885
- this.filterInput.nativeElement.focus();
886
- }
887
- }
888
- if (!this.filterable && isFirstNodeActive) {
900
+ // Current focus is on the filter input => should focus the wrapper
901
+ if (this.filterable && this.isFilterActive) {
889
902
  this.focus();
903
+ // Current focus is on the treeview first node => should focus the check all checkbox if enabled
904
+ }
905
+ else if (this.checkAll && !this.isCheckAllActive && isFirstNodeActive) {
906
+ this.checkAllInput.nativeElement.focus();
907
+ // Current focus is either on the check all checkbox or the treeview's first node
908
+ // => should focus either the filter input (if enabled) or the wrapper
909
+ }
910
+ else if (this.isCheckAllActive || isFirstNodeActive) {
911
+ this.filterable ?
912
+ this.filterInput.nativeElement.focus() :
913
+ this.focus();
890
914
  }
891
915
  }
892
916
  handleDownKey(event) {
@@ -894,9 +918,14 @@ let MultiSelectTreeComponent = MultiSelectTreeComponent_1 = class MultiSelectTre
894
918
  return;
895
919
  }
896
920
  event.originalEvent.preventDefault();
897
- // Put the focus back on the filter input if the wrapper is focused
921
+ // Current focus is on the wrapper => should focus the filter input
898
922
  if (this.filterable && this.isWrapperActive) {
899
923
  this.filterInput.nativeElement.focus();
924
+ // Current focus is on the wrapper/filter input => should focus check all checkbox if enabled
925
+ }
926
+ else if (this.checkAll && (this.isWrapperActive || this.isFilterActive)) {
927
+ this.checkAllInput.nativeElement.focus();
928
+ // Should focus the treeview if filterable and check all are disabled
900
929
  }
901
930
  else if (!this.treeview.isActive) {
902
931
  this.treeview.focus();
@@ -1054,6 +1083,10 @@ tslib_1.__decorate([
1054
1083
  ViewChild('filterInput', { static: false }),
1055
1084
  tslib_1.__metadata("design:type", ElementRef)
1056
1085
  ], MultiSelectTreeComponent.prototype, "filterInput", void 0);
1086
+ tslib_1.__decorate([
1087
+ ViewChild('checkAllInput', { static: false }),
1088
+ tslib_1.__metadata("design:type", ElementRef)
1089
+ ], MultiSelectTreeComponent.prototype, "checkAllInput", void 0);
1057
1090
  tslib_1.__decorate([
1058
1091
  Input(),
1059
1092
  tslib_1.__metadata("design:type", Number),
@@ -1136,6 +1169,10 @@ tslib_1.__decorate([
1136
1169
  Input(),
1137
1170
  tslib_1.__metadata("design:type", Boolean)
1138
1171
  ], MultiSelectTreeComponent.prototype, "filterable", void 0);
1172
+ tslib_1.__decorate([
1173
+ Input(),
1174
+ tslib_1.__metadata("design:type", Boolean)
1175
+ ], MultiSelectTreeComponent.prototype, "checkAll", void 0);
1139
1176
  tslib_1.__decorate([
1140
1177
  Input(),
1141
1178
  tslib_1.__metadata("design:type", Function)
@@ -1243,6 +1280,9 @@ MultiSelectTreeComponent = MultiSelectTreeComponent_1 = tslib_1.__decorate([
1243
1280
 
1244
1281
  i18n-clearTitle="kendo.multiselecttree.clearTitle|The title of the clear button"
1245
1282
  clearTitle="clear"
1283
+
1284
+ i18n-checkAllText="kendo.multiselecttree.checkAllText|The text displayed for the check-all checkbox"
1285
+ checkAllText="Check all"
1246
1286
  >
1247
1287
  </ng-container>
1248
1288
  <div #wrapper
@@ -1311,9 +1351,7 @@ MultiSelectTreeComponent = MultiSelectTreeComponent_1 = tslib_1.__decorate([
1311
1351
  #filterInput
1312
1352
  (input)="handleFilterInputChange($event.target.value)"
1313
1353
  [filterInput]="filterable && !touchEnabled"
1314
- (keydown.arrowdown)="handleKeydown($event)"
1315
- (keydown.arrowup)="handleKeydown($event)"
1316
- (keydown.alt.arrowup)="handleKeydown($event)"
1354
+ (keydown)="handleKeydown($event)"
1317
1355
  [(ngModel)]="filter"
1318
1356
  class="k-textbox"
1319
1357
  role="textbox"
@@ -1336,6 +1374,35 @@ MultiSelectTreeComponent = MultiSelectTreeComponent_1 = tslib_1.__decorate([
1336
1374
  templateRef: headerTemplate?.templateRef
1337
1375
  }">
1338
1376
  </ng-template>
1377
+ <div *ngIf="checkAll" class="k-check-all">
1378
+ <input
1379
+ #checkAllInput
1380
+ [checkAll]="!filterable && !touchEnabled"
1381
+ type="checkbox"
1382
+ class="k-checkbox"
1383
+ role="checkbox"
1384
+ tabindex="0"
1385
+ aria-disabled="false"
1386
+ aria-readonly="false"
1387
+ [treeview]="treeview"
1388
+ [checkedItems]="checkedItems"
1389
+ [valueField]="valueField"
1390
+ [lastAction]="lastAction"
1391
+ (checkedItemsChange)="handleCheckedItemsChange($event)"
1392
+ (keydown)="handleKeydown($event)"
1393
+ [kendoEventsOutsideAngular]="{
1394
+ blur: handleBlur
1395
+ }"
1396
+ [scope]="this"
1397
+ >
1398
+ <span
1399
+ class="k-checkbox-label"
1400
+ (click)="toggleCheckAll()"
1401
+ (mousedown)="$event.preventDefault()"
1402
+ >
1403
+ {{ messageFor('checkAllText') }}
1404
+ </span>
1405
+ </div>
1339
1406
  <kendo-treeview
1340
1407
  #treeview
1341
1408
  [nodes]="data"
@@ -24,5 +24,7 @@ export { TagListComponent } from './common/taglist.component';
24
24
  export { NoDataTemplateDirective } from './common/templates/no-data-template.directive';
25
25
  export { TagTemplateDirective } from './common/templates/tag-template.directive';
26
26
  export { DROPDOWNLIST_VALUE_ACCESSOR } from './dropdownlist/dropdownlist.component';
27
+ export { BaseCheckDirective } from './dropdowntrees/checked-state/base-check.directive';
28
+ export { CheckAllDirective } from './dropdowntrees/checked-state/check-all.directive';
27
29
  export { CheckDirective } from './dropdowntrees/checked-state/check.directive';
28
30
  export { MultiSelectTreeSummaryTagDirective } from './dropdowntrees/summary-tag/summary-tag.directive';
@@ -24,5 +24,7 @@ export { TagListComponent } from './common/taglist.component';
24
24
  export { NoDataTemplateDirective } from './common/templates/no-data-template.directive';
25
25
  export { TagTemplateDirective } from './common/templates/tag-template.directive';
26
26
  export { DROPDOWNLIST_VALUE_ACCESSOR } from './dropdownlist/dropdownlist.component';
27
+ export { BaseCheckDirective } from './dropdowntrees/checked-state/base-check.directive';
28
+ export { CheckAllDirective } from './dropdowntrees/checked-state/check-all.directive';
27
29
  export { CheckDirective } from './dropdowntrees/checked-state/check.directive';
28
30
  export { MultiSelectTreeSummaryTagDirective } from './dropdowntrees/summary-tag/summary-tag.directive';