@progress/kendo-angular-filter 2.2.3-dev.202210120943 → 2.3.0-dev.202210180721

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 (33) hide show
  1. package/aria-label.directive.d.ts +1 -1
  2. package/base-filter-row.component.d.ts +28 -0
  3. package/bundles/kendo-angular-filter.umd.js +1 -1
  4. package/editors/boolean-editor.component.d.ts +1 -0
  5. package/editors/date-editor.component.d.ts +1 -0
  6. package/editors/numeric-editor.component.d.ts +1 -0
  7. package/editors/text-editor.component.d.ts +1 -0
  8. package/error-messages.d.ts +8 -0
  9. package/esm2015/aria-label.directive.js +2 -2
  10. package/esm2015/base-filter-row.component.js +69 -0
  11. package/esm2015/editors/boolean-editor.component.js +10 -4
  12. package/esm2015/editors/date-editor.component.js +10 -4
  13. package/esm2015/editors/numeric-editor.component.js +10 -4
  14. package/esm2015/editors/text-editor.component.js +10 -4
  15. package/esm2015/error-messages.js +16 -0
  16. package/esm2015/filter-expression-operators.component.js +2 -0
  17. package/esm2015/filter-expression.component.js +60 -47
  18. package/esm2015/filter-group.component.js +76 -38
  19. package/esm2015/filter.component.js +107 -32
  20. package/esm2015/filter.module.js +2 -1
  21. package/esm2015/localization/messages.js +3 -3
  22. package/esm2015/navigation.service.js +159 -0
  23. package/esm2015/package-metadata.js +1 -1
  24. package/esm2015/util.js +33 -0
  25. package/fesm2015/kendo-angular-filter.js +523 -122
  26. package/filter-expression.component.d.ts +7 -10
  27. package/filter-group.component.d.ts +11 -10
  28. package/filter.component.d.ts +24 -4
  29. package/localization/messages.d.ts +3 -3
  30. package/model/filter-expression.d.ts +1 -1
  31. package/navigation.service.d.ts +40 -0
  32. package/package.json +1 -1
  33. package/util.d.ts +12 -0
@@ -2,30 +2,33 @@
2
2
  * Copyright © 2021 Progress Software Corporation. All rights reserved.
3
3
  * Licensed under commercial license. See LICENSE.md in the project root for more information
4
4
  *-------------------------------------------------------------------------------------------*/
5
- import { Component, EventEmitter, Input, Output } from '@angular/core';
6
- import { getKeyByValue, localizeOperators, logicOperators } from './util';
5
+ import { Component, forwardRef, Input, ViewChildren } from '@angular/core';
6
+ import { BaseFilterRowComponent } from './base-filter-row.component';
7
+ import { FilterItem, getKeyByValue, localizeOperators, logicOperators, selectors } from './util';
7
8
  import * as i0 from "@angular/core";
8
9
  import * as i1 from "./filter.service";
9
- import * as i2 from "@progress/kendo-angular-l10n";
10
- import * as i3 from "./filter-expression.component";
11
- import * as i4 from "@angular/common";
12
- import * as i5 from "@progress/kendo-angular-buttons";
10
+ import * as i2 from "./navigation.service";
11
+ import * as i3 from "@progress/kendo-angular-l10n";
12
+ import * as i4 from "./filter-expression.component";
13
+ import * as i5 from "@angular/common";
14
+ import * as i6 from "@progress/kendo-angular-buttons";
13
15
  /**
14
16
  * @hidden
15
17
  */
16
- export class FilterGroupComponent {
17
- constructor(filterService, localization, cdr) {
18
+ export class FilterGroupComponent extends BaseFilterRowComponent {
19
+ constructor(filterService, cdr, element, navigationService, localization, renderer) {
20
+ super(element, navigationService, localization, renderer);
18
21
  this.filterService = filterService;
19
- this.localization = localization;
20
22
  this.cdr = cdr;
21
- this.index = 0;
22
23
  this.currentItem = {
23
24
  logic: 'or',
24
25
  filters: []
25
26
  };
26
- this.valueChange = new EventEmitter();
27
27
  this.operators = [];
28
28
  }
29
+ get filterItems() {
30
+ return this._filterItems.toArray();
31
+ }
29
32
  ngOnInit() {
30
33
  this.operators = this.getLogicOperators();
31
34
  this.localizationSubscription = this.localization.changes.subscribe(() => {
@@ -41,9 +44,6 @@ export class FilterGroupComponent {
41
44
  getLogicOperators() {
42
45
  return localizeOperators(logicOperators)(this.localization);
43
46
  }
44
- messageFor(key) {
45
- return this.localization.get(key);
46
- }
47
47
  getOperator(operatorValue) {
48
48
  return this.messageFor(getKeyByValue(logicOperators, operatorValue));
49
49
  }
@@ -63,16 +63,44 @@ export class FilterGroupComponent {
63
63
  }
64
64
  removeFilterGroup() {
65
65
  this.filterService.remove(this.currentItem, this.index);
66
- this.valueChange.emit();
66
+ this.cdr.detectChanges();
67
+ this.valueChange.emit(true);
68
+ }
69
+ onMouseDown(event) {
70
+ let elementToFocus;
71
+ if (event.target.closest(selectors.kendoFilterToolbarItem)) {
72
+ let index = Array.from(event.target.closest(selectors.kendoToolbar).children).indexOf(event.target.closest(selectors.kendoFilterToolbarItem)) + 1;
73
+ if (event.target.closest(selectors.andButton)) {
74
+ index = 0;
75
+ }
76
+ if (event.target.closest(selectors.orButton)) {
77
+ index = 1;
78
+ }
79
+ this.navigationService.currentToolbarItemChildrenIndex = index;
80
+ this.navigationService.isInnerNavigationActivated = true;
81
+ elementToFocus = this.navigationService.flattenFilterItems[this.itemNumber].focusableChildren[index];
82
+ }
83
+ else {
84
+ this.navigationService.currentToolbarItemChildrenIndex = 0;
85
+ this.navigationService.isInnerNavigationActivated = false;
86
+ elementToFocus = this.navigationService.flattenFilterItems[this.itemNumber].toolbarElement;
87
+ }
88
+ this.navigationService.isFilterExpressionComponentFocused = false;
89
+ this.navigationService.currentToolbarItemIndex = this.itemNumber;
90
+ this.navigationService.focusCurrentElement(elementToFocus, true);
67
91
  }
68
92
  }
69
- FilterGroupComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FilterGroupComponent, deps: [{ token: i1.FilterService }, { token: i2.LocalizationService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
70
- FilterGroupComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.16", type: FilterGroupComponent, selector: "kendo-filter-group", inputs: { index: "index", currentItem: "currentItem" }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: `
71
- <div class="k-filter-toolbar" role="toolbar" [attr.aria-label]="messageFor('filterToolbarAriaLabel')">
72
- <div class="k-toolbar">
93
+ FilterGroupComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FilterGroupComponent, deps: [{ token: i1.FilterService }, { token: i0.ChangeDetectorRef }, { token: i0.ElementRef }, { token: i2.NavigationService }, { token: i3.LocalizationService }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component });
94
+ FilterGroupComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.16", type: FilterGroupComponent, selector: "kendo-filter-group", inputs: { currentItem: "currentItem" }, providers: [{
95
+ provide: FilterItem,
96
+ useExisting: forwardRef(() => FilterGroupComponent)
97
+ }], viewQueries: [{ propertyName: "_filterItems", predicate: FilterItem, descendants: true }], usesInheritance: true, ngImport: i0, template: `
98
+ <div class="k-filter-toolbar">
99
+ <div class="k-toolbar" role="toolbar" [attr.aria-label]="messageFor('filterToolbarAriaLabel')" (focus)="onFocus()" (focusout)="onBlur()" (mousedown)="onMouseDown($event)">
73
100
  <div class="k-filter-toolbar-item">
74
101
  <div class="k-widget k-button-group" role="group">
75
- <button
102
+ <button
103
+ tabindex="-1"
76
104
  *ngFor="let operator of operators"
77
105
  kendoButton
78
106
  [ngClass]="{'k-group-start': operator.value === 'and', 'k-group-end': operator.value === 'or'}"
@@ -87,6 +115,7 @@ FilterGroupComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", v
87
115
  <div class="k-filter-toolbar-item">
88
116
  <button
89
117
  kendoButton
118
+ tabindex="-1"
90
119
  [title]="messageFor('addFilter')"
91
120
  icon="filter-add-expression"
92
121
  (click)="addFilterExpression()">
@@ -96,6 +125,7 @@ FilterGroupComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", v
96
125
  <div class="k-filter-toolbar-item">
97
126
  <button
98
127
  kendoButton
128
+ tabindex="-1"
99
129
  [title]="messageFor('addGroup')"
100
130
  icon="filter-add-group"
101
131
  (click)="addFilterGroup()">
@@ -105,6 +135,7 @@ FilterGroupComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", v
105
135
  <div class="k-filter-toolbar-item">
106
136
  <button
107
137
  kendoButton
138
+ tabindex="-1"
108
139
  icon="x"
109
140
  fillMode="flat"
110
141
  [title]="messageFor('remove')"
@@ -114,15 +145,15 @@ FilterGroupComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", v
114
145
  </div>
115
146
  </div>
116
147
 
117
- <ul class="k-filter-lines" *ngIf="currentItem.filters">
148
+ <ul class="k-filter-lines" role="group" *ngIf="currentItem.filters">
118
149
  <ng-container *ngFor="let item of currentItem.filters; let i = index;">
119
- <li class="k-filter-item" *ngIf="!item['filters']">
120
- <kendo-filter-expression (valueChange)="valueChange.emit()" [currentItem]="item" [index]="i">
150
+ <li class="k-filter-item" role="treeitem" *ngIf="!item['filters']">
151
+ <kendo-filter-expression (valueChange)="valueChange.emit($event)" [currentItem]="item" [index]="i">
121
152
  </kendo-filter-expression>
122
153
  </li>
123
- <li class="k-filter-item" *ngIf="item['filters']">
154
+ <li class="k-filter-item" role="treeitem" *ngIf="item['filters']">
124
155
  <kendo-filter-group
125
- (valueChange)="valueChange.emit()"
156
+ (valueChange)="valueChange.emit($event)"
126
157
  [currentItem]="item"
127
158
  [index]="i"
128
159
  >
@@ -130,17 +161,22 @@ FilterGroupComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", v
130
161
  </li>
131
162
  </ng-container>
132
163
  </ul>
133
- `, isInline: true, components: [{ type: i3.FilterExpressionComponent, selector: "kendo-filter-expression", inputs: ["index", "currentItem"], outputs: ["valueChange"] }, { type: FilterGroupComponent, selector: "kendo-filter-group", inputs: ["index", "currentItem"], outputs: ["valueChange"] }], directives: [{ type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i5.ButtonDirective, selector: "button[kendoButton], span[kendoButton]", inputs: ["toggleable", "togglable", "selected", "tabIndex", "icon", "iconClass", "imageUrl", "disabled", "size", "rounded", "fillMode", "themeColor", "role", "primary", "look"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
164
+ `, isInline: true, components: [{ type: i4.FilterExpressionComponent, selector: "kendo-filter-expression", inputs: ["currentItem"] }, { type: FilterGroupComponent, selector: "kendo-filter-group", inputs: ["currentItem"] }], directives: [{ type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i6.ButtonDirective, selector: "button[kendoButton], span[kendoButton]", inputs: ["toggleable", "togglable", "selected", "tabIndex", "icon", "iconClass", "imageUrl", "disabled", "size", "rounded", "fillMode", "themeColor", "role", "primary", "look"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
134
165
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FilterGroupComponent, decorators: [{
135
166
  type: Component,
136
167
  args: [{
168
+ providers: [{
169
+ provide: FilterItem,
170
+ useExisting: forwardRef(() => FilterGroupComponent)
171
+ }],
137
172
  selector: 'kendo-filter-group',
138
173
  template: `
139
- <div class="k-filter-toolbar" role="toolbar" [attr.aria-label]="messageFor('filterToolbarAriaLabel')">
140
- <div class="k-toolbar">
174
+ <div class="k-filter-toolbar">
175
+ <div class="k-toolbar" role="toolbar" [attr.aria-label]="messageFor('filterToolbarAriaLabel')" (focus)="onFocus()" (focusout)="onBlur()" (mousedown)="onMouseDown($event)">
141
176
  <div class="k-filter-toolbar-item">
142
177
  <div class="k-widget k-button-group" role="group">
143
- <button
178
+ <button
179
+ tabindex="-1"
144
180
  *ngFor="let operator of operators"
145
181
  kendoButton
146
182
  [ngClass]="{'k-group-start': operator.value === 'and', 'k-group-end': operator.value === 'or'}"
@@ -155,6 +191,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImpo
155
191
  <div class="k-filter-toolbar-item">
156
192
  <button
157
193
  kendoButton
194
+ tabindex="-1"
158
195
  [title]="messageFor('addFilter')"
159
196
  icon="filter-add-expression"
160
197
  (click)="addFilterExpression()">
@@ -164,6 +201,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImpo
164
201
  <div class="k-filter-toolbar-item">
165
202
  <button
166
203
  kendoButton
204
+ tabindex="-1"
167
205
  [title]="messageFor('addGroup')"
168
206
  icon="filter-add-group"
169
207
  (click)="addFilterGroup()">
@@ -173,6 +211,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImpo
173
211
  <div class="k-filter-toolbar-item">
174
212
  <button
175
213
  kendoButton
214
+ tabindex="-1"
176
215
  icon="x"
177
216
  fillMode="flat"
178
217
  [title]="messageFor('remove')"
@@ -182,15 +221,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImpo
182
221
  </div>
183
222
  </div>
184
223
 
185
- <ul class="k-filter-lines" *ngIf="currentItem.filters">
224
+ <ul class="k-filter-lines" role="group" *ngIf="currentItem.filters">
186
225
  <ng-container *ngFor="let item of currentItem.filters; let i = index;">
187
- <li class="k-filter-item" *ngIf="!item['filters']">
188
- <kendo-filter-expression (valueChange)="valueChange.emit()" [currentItem]="item" [index]="i">
226
+ <li class="k-filter-item" role="treeitem" *ngIf="!item['filters']">
227
+ <kendo-filter-expression (valueChange)="valueChange.emit($event)" [currentItem]="item" [index]="i">
189
228
  </kendo-filter-expression>
190
229
  </li>
191
- <li class="k-filter-item" *ngIf="item['filters']">
230
+ <li class="k-filter-item" role="treeitem" *ngIf="item['filters']">
192
231
  <kendo-filter-group
193
- (valueChange)="valueChange.emit()"
232
+ (valueChange)="valueChange.emit($event)"
194
233
  [currentItem]="item"
195
234
  [index]="i"
196
235
  >
@@ -200,10 +239,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImpo
200
239
  </ul>
201
240
  `
202
241
  }]
203
- }], ctorParameters: function () { return [{ type: i1.FilterService }, { type: i2.LocalizationService }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { index: [{
204
- type: Input
242
+ }], ctorParameters: function () { return [{ type: i1.FilterService }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }, { type: i2.NavigationService }, { type: i3.LocalizationService }, { type: i0.Renderer2 }]; }, propDecorators: { _filterItems: [{
243
+ type: ViewChildren,
244
+ args: [FilterItem]
205
245
  }], currentItem: [{
206
246
  type: Input
207
- }], valueChange: [{
208
- type: Output
209
247
  }] } });
@@ -2,18 +2,23 @@
2
2
  * Copyright © 2021 Progress Software Corporation. All rights reserved.
3
3
  * Licensed under commercial license. See LICENSE.md in the project root for more information
4
4
  *-------------------------------------------------------------------------------------------*/
5
- import { Component, Input, Output, EventEmitter, HostBinding, isDevMode, ContentChildren } from '@angular/core';
5
+ import { Component, Input, Output, EventEmitter, HostBinding, isDevMode, ContentChildren, HostListener, ViewChildren } from '@angular/core';
6
6
  import { L10N_PREFIX, LocalizationService } from '@progress/kendo-angular-l10n';
7
7
  import { FilterService } from './filter.service';
8
8
  import { nullOperators, isPresent } from './util';
9
9
  import { validatePackage } from '@progress/kendo-licensing';
10
10
  import { packageMetadata } from './package-metadata';
11
11
  import { FilterFieldComponent } from './filter-field.component';
12
+ import { FilterItem } from './util';
13
+ import { NavigationService } from './navigation.service';
14
+ import { Keys } from '@progress/kendo-angular-common';
15
+ import { FilterErrorMessages } from './error-messages';
12
16
  import * as i0 from "@angular/core";
13
17
  import * as i1 from "./filter.service";
14
18
  import * as i2 from "@progress/kendo-angular-l10n";
15
- import * as i3 from "./filter-group.component";
16
- import * as i4 from "./localization/localized-messages.directive";
19
+ import * as i3 from "./navigation.service";
20
+ import * as i4 from "./filter-group.component";
21
+ import * as i5 from "./localization/localized-messages.directive";
17
22
  /**
18
23
  * Represents the [Kendo UI Filter component for Angular]({% slug overview_filter %}).
19
24
  * The Filter component can be used to apply any user defined filter criteria.
@@ -47,10 +52,13 @@ import * as i4 from "./localization/localized-messages.directive";
47
52
  * ```
48
53
  */
49
54
  export class FilterComponent {
50
- constructor(filterService, localization, cdr) {
55
+ constructor(filterService, localization, cdr, element, navigationService, renderer) {
51
56
  this.filterService = filterService;
52
57
  this.localization = localization;
53
58
  this.cdr = cdr;
59
+ this.element = element;
60
+ this.navigationService = navigationService;
61
+ this.renderer = renderer;
54
62
  /**
55
63
  * Fires every time the Filter component value is updated.
56
64
  * That is each time a Filter Group or Filter Expression is added, removed, or updated.
@@ -60,6 +68,31 @@ export class FilterComponent {
60
68
  validatePackage(packageMetadata);
61
69
  this.direction = localization.rtl ? 'rtl' : 'ltr';
62
70
  }
71
+ /**
72
+ * @hidden
73
+ */
74
+ focusout() {
75
+ setTimeout(() => {
76
+ if (!(document.activeElement.closest('.k-filter'))) {
77
+ this.renderer.setAttribute(this.navigationService.currentlyFocusedElement, 'tabindex', '-1');
78
+ this.navigationService.currentlyFocusedElement = this.navigationService.flattenFilterItems[this.navigationService.currentToolbarItemIndex].toolbarElement;
79
+ this.renderer.setAttribute(this.navigationService.currentlyFocusedElement, 'tabindex', '0');
80
+ this.navigationService.isInnerNavigationActivated = false;
81
+ this.navigationService.isFilterExpressionComponentFocused = false;
82
+ }
83
+ });
84
+ }
85
+ /**
86
+ * @hidden
87
+ */
88
+ onKeydown(event) {
89
+ const keyCode = event.keyCode;
90
+ const keys = [Keys.ArrowUp, Keys.ArrowDown, Keys.ArrowLeft, Keys.ArrowRight, Keys.Enter,
91
+ Keys.Escape, Keys.Tab];
92
+ if (keys.indexOf(keyCode) > -1) {
93
+ this.navigationService.processKeyDown(keyCode, event);
94
+ }
95
+ }
63
96
  /**
64
97
  * Specifies the available user-defined filters. At least one filter should be provided.
65
98
  */
@@ -91,13 +124,19 @@ export class FilterComponent {
91
124
  get value() {
92
125
  return this._value;
93
126
  }
127
+ get filterItems() {
128
+ return this._filterItems.toArray();
129
+ }
130
+ get toolbarElement() {
131
+ return this.element.nativeElement.querySelector('.k-toolbar');
132
+ }
94
133
  ngOnInit() {
95
134
  this.localizationSubscription = this.localization.changes.subscribe(({ rtl }) => {
96
135
  this.direction = rtl ? 'rtl' : 'ltr';
97
136
  this.cdr.detectChanges();
98
137
  });
99
138
  }
100
- ngAfterViewChecked() {
139
+ ngAfterViewInit() {
101
140
  if (this.filterFields && this.filterFields.length > 0) {
102
141
  this.filters = this.filterFields.map((filterField) => {
103
142
  var _a;
@@ -105,7 +144,13 @@ export class FilterComponent {
105
144
  });
106
145
  }
107
146
  if (this.filters.length === 0) {
108
- throw new Error(`Pass at least one user-defined filter through the [filters] input property or nest kendo-filter-field components. See http://www.telerik.com/kendo-angular-ui/components/filter/#data-binding`);
147
+ throw new Error(FilterErrorMessages.missingFilters);
148
+ }
149
+ this.navigationService.reset(this.filterItems);
150
+ if (!this.navigationService.currentlyFocusedElement) {
151
+ const firstElement = this.navigationService.flattenFilterItems[0].toolbarElement;
152
+ this.navigationService.currentlyFocusedElement = firstElement;
153
+ this.renderer.setAttribute(firstElement, 'tabindex', '0');
109
154
  }
110
155
  }
111
156
  ngOnDestroy() {
@@ -122,22 +167,35 @@ export class FilterComponent {
122
167
  /**
123
168
  * @hidden
124
169
  */
125
- onValueChange() {
170
+ onValueChange(isRemoveOperation) {
126
171
  this.valueChange.emit(this.filterService.normalizedValue);
172
+ this.cdr.detectChanges();
173
+ this.navigationService.reset(this.filterItems);
174
+ if (isRemoveOperation) {
175
+ if (this.navigationService.currentToolbarItemIndex === this.navigationService.flattenFilterItems.length) {
176
+ this.navigationService.currentToolbarItemIndex -= 1;
177
+ }
178
+ this.navigationService.isInnerNavigationActivated = false;
179
+ this.navigationService.isFilterExpressionComponentFocused = false;
180
+ this.navigationService.currentlyFocusedElement = this.navigationService.flattenFilterItems[this.navigationService.currentToolbarItemIndex].toolbarElement;
181
+ this.renderer.setAttribute(this.navigationService.currentlyFocusedElement, 'tabindex', '0');
182
+ this.renderer.addClass(this.navigationService.currentlyFocusedElement, 'k-focus');
183
+ this.navigationService.currentlyFocusedElement.focus();
184
+ }
127
185
  }
128
186
  normalizeFilter(filterDescriptor) {
129
187
  const foundFilter = this.filterService.filters.find((filter) => filter.field === filterDescriptor.field);
130
188
  if (isDevMode() && !foundFilter) {
131
- throw new Error(`There is no user-defined filter with '${filterDescriptor.field}' field provided through the [filters] input property.`);
189
+ throw new Error(FilterErrorMessages.missingFilterForUsedField(filterDescriptor.field));
132
190
  }
133
191
  if (isDevMode() && foundFilter.editor === 'boolean' && (!filterDescriptor.value && filterDescriptor.value !== false)) {
134
- console.warn(`Provide a value for the boolean '${filterDescriptor.field}' user-defined filter as the operator is always set to 'eq'.`);
192
+ console.warn(FilterErrorMessages.missingValueForBooleanField(filterDescriptor.field));
135
193
  }
136
194
  if (isDevMode() && foundFilter.editor === 'boolean' && filterDescriptor.operator !== 'eq') {
137
- console.warn(`The operator of the boolean '${filterDescriptor.field}' user-defined filter is always set to 'eq'.`);
195
+ console.warn(FilterErrorMessages.operatorBooleanField(filterDescriptor.field));
138
196
  }
139
197
  if (filterDescriptor.operator && foundFilter.operators && !foundFilter.operators.some(operator => operator === filterDescriptor.operator)) {
140
- throw new Error(`The user-defined filter with field '${filterDescriptor.field}' is missing the '${filterDescriptor.operator}' operator.`);
198
+ throw new Error(FilterErrorMessages.filterMissingUsedOperator(filterDescriptor.field, filterDescriptor.operator));
141
199
  }
142
200
  if (foundFilter.editor === 'boolean') {
143
201
  filterDescriptor.operator = 'eq';
@@ -170,16 +228,23 @@ export class FilterComponent {
170
228
  }
171
229
  });
172
230
  }
231
+ /**
232
+ * @hidden
233
+ */
234
+ messageFor(key) {
235
+ return this.localization.get(key);
236
+ }
173
237
  }
174
- FilterComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FilterComponent, deps: [{ token: i1.FilterService }, { token: i2.LocalizationService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
175
- FilterComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.16", type: FilterComponent, selector: "kendo-filter", inputs: { filters: "filters", value: "value" }, outputs: { valueChange: "valueChange" }, host: { properties: { "attr.dir": "this.direction" } }, providers: [
238
+ FilterComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FilterComponent, deps: [{ token: i1.FilterService }, { token: i2.LocalizationService }, { token: i0.ChangeDetectorRef }, { token: i0.ElementRef }, { token: i3.NavigationService }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component });
239
+ FilterComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.16", type: FilterComponent, selector: "kendo-filter", inputs: { filters: "filters", value: "value" }, outputs: { valueChange: "valueChange" }, host: { listeners: { "focusout": "focusout($event)", "keydown": "onKeydown($event)" }, properties: { "attr.dir": "this.direction" } }, providers: [
176
240
  LocalizationService,
177
241
  {
178
242
  provide: L10N_PREFIX,
179
243
  useValue: 'kendo.filter'
180
244
  },
181
- FilterService
182
- ], queries: [{ propertyName: "filterFields", predicate: FilterFieldComponent }], ngImport: i0, template: `
245
+ FilterService,
246
+ NavigationService
247
+ ], queries: [{ propertyName: "filterFields", predicate: FilterFieldComponent }], viewQueries: [{ propertyName: "_filterItems", predicate: FilterItem, descendants: true }], ngImport: i0, template: `
183
248
  <ng-container kendoFilterLocalizedMessages
184
249
  i18n-editorDateTodayText="kendo.filter.editorDateTodayText|The text of the Today button of the Date editor"
185
250
  editorDateTodayText="Today"
@@ -286,25 +351,25 @@ FilterComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", versio
286
351
  i18n-filterValueAriaLabel="kendo.filter.filterValueAriaLabel|The text of the filter value aria label"
287
352
  filterValueAriaLabel="value"
288
353
 
289
- i18n-filterAriaLabel="kendo.filter.filterAriaLabel|The text of the filter row aria label"
290
- filterAriaLabel="filter"
354
+ i18n-filterToolbarAriaLabel="kendo.filter.filterToolbarAriaLabel|The text of the filter row aria label"
355
+ filterToolbarAriaLabel="filter row settings"
291
356
 
292
- i18n-filterToolbarAriaLabel="kendo.filter.filterToolbarAriaLabel|The text of the filter toolbar aria label"
293
- filterToolbarAriaLabel="filter settings"
357
+ i18n-filterComponentAriaLabel="kendo.filter.filterComponentAriaLabel|The text of the filter component aria label"
358
+ filterComponentAriaLabel="filter component"
294
359
  >
295
360
  </ng-container>
296
361
  <div class="k-widget k-filter" [attr.dir]="direction">
297
- <ul class='k-filter-container'>
298
- <li class='k-filter-group-main'>
362
+ <ul class='k-filter-container' role="tree" [attr.aria-label]="messageFor('filterComponentAriaLabel')">
363
+ <li class='k-filter-group-main' role="treeitem">
299
364
  <kendo-filter-group
300
365
  [currentItem]="getCurrentFilter()"
301
- (valueChange)="onValueChange()"
366
+ (valueChange)="onValueChange($event)"
302
367
  >
303
368
  </kendo-filter-group>
304
369
  </li>
305
370
  </ul>
306
371
  </div>
307
- `, isInline: true, components: [{ type: i3.FilterGroupComponent, selector: "kendo-filter-group", inputs: ["index", "currentItem"], outputs: ["valueChange"] }], directives: [{ type: i4.LocalizedMessagesDirective, selector: "[kendoFilterLocalizedMessages]" }] });
372
+ `, isInline: true, components: [{ type: i4.FilterGroupComponent, selector: "kendo-filter-group", inputs: ["currentItem"] }], directives: [{ type: i5.LocalizedMessagesDirective, selector: "[kendoFilterLocalizedMessages]" }] });
308
373
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: FilterComponent, decorators: [{
309
374
  type: Component,
310
375
  args: [{
@@ -314,7 +379,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImpo
314
379
  provide: L10N_PREFIX,
315
380
  useValue: 'kendo.filter'
316
381
  },
317
- FilterService
382
+ FilterService,
383
+ NavigationService
318
384
  ],
319
385
  selector: 'kendo-filter',
320
386
  template: `
@@ -424,19 +490,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImpo
424
490
  i18n-filterValueAriaLabel="kendo.filter.filterValueAriaLabel|The text of the filter value aria label"
425
491
  filterValueAriaLabel="value"
426
492
 
427
- i18n-filterAriaLabel="kendo.filter.filterAriaLabel|The text of the filter row aria label"
428
- filterAriaLabel="filter"
493
+ i18n-filterToolbarAriaLabel="kendo.filter.filterToolbarAriaLabel|The text of the filter row aria label"
494
+ filterToolbarAriaLabel="filter row settings"
429
495
 
430
- i18n-filterToolbarAriaLabel="kendo.filter.filterToolbarAriaLabel|The text of the filter toolbar aria label"
431
- filterToolbarAriaLabel="filter settings"
496
+ i18n-filterComponentAriaLabel="kendo.filter.filterComponentAriaLabel|The text of the filter component aria label"
497
+ filterComponentAriaLabel="filter component"
432
498
  >
433
499
  </ng-container>
434
500
  <div class="k-widget k-filter" [attr.dir]="direction">
435
- <ul class='k-filter-container'>
436
- <li class='k-filter-group-main'>
501
+ <ul class='k-filter-container' role="tree" [attr.aria-label]="messageFor('filterComponentAriaLabel')">
502
+ <li class='k-filter-group-main' role="treeitem">
437
503
  <kendo-filter-group
438
504
  [currentItem]="getCurrentFilter()"
439
- (valueChange)="onValueChange()"
505
+ (valueChange)="onValueChange($event)"
440
506
  >
441
507
  </kendo-filter-group>
442
508
  </li>
@@ -444,7 +510,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImpo
444
510
  </div>
445
511
  `
446
512
  }]
447
- }], ctorParameters: function () { return [{ type: i1.FilterService }, { type: i2.LocalizationService }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { direction: [{
513
+ }], ctorParameters: function () { return [{ type: i1.FilterService }, { type: i2.LocalizationService }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }, { type: i3.NavigationService }, { type: i0.Renderer2 }]; }, propDecorators: { focusout: [{
514
+ type: HostListener,
515
+ args: ['focusout', ['$event']]
516
+ }], onKeydown: [{
517
+ type: HostListener,
518
+ args: ['keydown', ['$event']]
519
+ }], direction: [{
448
520
  type: HostBinding,
449
521
  args: ['attr.dir']
450
522
  }], filters: [{
@@ -456,4 +528,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImpo
456
528
  }], filterFields: [{
457
529
  type: ContentChildren,
458
530
  args: [FilterFieldComponent]
531
+ }], _filterItems: [{
532
+ type: ViewChildren,
533
+ args: [FilterItem]
459
534
  }] } });
@@ -108,6 +108,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImpo
108
108
  CustomMessagesComponent,
109
109
  AriaLabelValueDirective,
110
110
  FilterFieldComponent,
111
- FilterValueEditorTemplateDirective]
111
+ FilterValueEditorTemplateDirective
112
+ ]
112
113
  }]
113
114
  }] });
@@ -12,7 +12,7 @@ import * as i0 from "@angular/core";
12
12
  export class Messages extends ComponentMessages {
13
13
  }
14
14
  Messages.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: Messages, deps: null, target: i0.ɵɵFactoryTarget.Directive });
15
- Messages.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "12.2.16", type: Messages, selector: "[kendoFilterMessages]", inputs: { filterExpressionOperators: "filterExpressionOperators", filterExpressionFilters: "filterExpressionFilters", remove: "remove", addGroup: "addGroup", addFilter: "addFilter", filterAndLogic: "filterAndLogic", filterOrLogic: "filterOrLogic", filterEqOperator: "filterEqOperator", filterNotEqOperator: "filterNotEqOperator", filterIsNullOperator: "filterIsNullOperator", filterIsNotNullOperator: "filterIsNotNullOperator", filterIsEmptyOperator: "filterIsEmptyOperator", filterIsNotEmptyOperator: "filterIsNotEmptyOperator", filterStartsWithOperator: "filterStartsWithOperator", filterContainsOperator: "filterContainsOperator", filterNotContainsOperator: "filterNotContainsOperator", filterEndsWithOperator: "filterEndsWithOperator", filterGteOperator: "filterGteOperator", filterGtOperator: "filterGtOperator", filterLteOperator: "filterLteOperator", filterLtOperator: "filterLtOperator", filterIsTrue: "filterIsTrue", filterIsFalse: "filterIsFalse", filterBooleanAll: "filterBooleanAll", filterAfterOrEqualOperator: "filterAfterOrEqualOperator", filterAfterOperator: "filterAfterOperator", filterBeforeOperator: "filterBeforeOperator", filterBeforeOrEqualOperator: "filterBeforeOrEqualOperator", editorNumericDecrement: "editorNumericDecrement", editorNumericIncrement: "editorNumericIncrement", editorDateTodayText: "editorDateTodayText", editorDateToggleText: "editorDateToggleText", filterFieldAriaLabel: "filterFieldAriaLabel", filterOperatorAriaLabel: "filterOperatorAriaLabel", filterValueAriaLabel: "filterValueAriaLabel", filterAriaLabel: "filterAriaLabel", filterToolbarAriaLabel: "filterToolbarAriaLabel" }, usesInheritance: true, ngImport: i0 });
15
+ Messages.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "12.2.16", type: Messages, selector: "[kendoFilterMessages]", inputs: { filterExpressionOperators: "filterExpressionOperators", filterExpressionFilters: "filterExpressionFilters", remove: "remove", addGroup: "addGroup", addFilter: "addFilter", filterAndLogic: "filterAndLogic", filterOrLogic: "filterOrLogic", filterEqOperator: "filterEqOperator", filterNotEqOperator: "filterNotEqOperator", filterIsNullOperator: "filterIsNullOperator", filterIsNotNullOperator: "filterIsNotNullOperator", filterIsEmptyOperator: "filterIsEmptyOperator", filterIsNotEmptyOperator: "filterIsNotEmptyOperator", filterStartsWithOperator: "filterStartsWithOperator", filterContainsOperator: "filterContainsOperator", filterNotContainsOperator: "filterNotContainsOperator", filterEndsWithOperator: "filterEndsWithOperator", filterGteOperator: "filterGteOperator", filterGtOperator: "filterGtOperator", filterLteOperator: "filterLteOperator", filterLtOperator: "filterLtOperator", filterIsTrue: "filterIsTrue", filterIsFalse: "filterIsFalse", filterBooleanAll: "filterBooleanAll", filterAfterOrEqualOperator: "filterAfterOrEqualOperator", filterAfterOperator: "filterAfterOperator", filterBeforeOperator: "filterBeforeOperator", filterBeforeOrEqualOperator: "filterBeforeOrEqualOperator", editorNumericDecrement: "editorNumericDecrement", editorNumericIncrement: "editorNumericIncrement", editorDateTodayText: "editorDateTodayText", editorDateToggleText: "editorDateToggleText", filterFieldAriaLabel: "filterFieldAriaLabel", filterOperatorAriaLabel: "filterOperatorAriaLabel", filterValueAriaLabel: "filterValueAriaLabel", filterToolbarAriaLabel: "filterToolbarAriaLabel", filterComponentAriaLabel: "filterComponentAriaLabel" }, usesInheritance: true, ngImport: i0 });
16
16
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: Messages, decorators: [{
17
17
  type: Directive,
18
18
  args: [{
@@ -88,8 +88,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImpo
88
88
  type: Input
89
89
  }], filterValueAriaLabel: [{
90
90
  type: Input
91
- }], filterAriaLabel: [{
92
- type: Input
93
91
  }], filterToolbarAriaLabel: [{
94
92
  type: Input
93
+ }], filterComponentAriaLabel: [{
94
+ type: Input
95
95
  }] } });