@progress/kendo-angular-filter
Version:
Kendo UI Angular Filter
290 lines (281 loc) • 13.6 kB
JavaScript
/**-----------------------------------------------------------------------------------------
* Copyright © 2025 Progress Software Corporation. All rights reserved.
* Licensed under commercial license. See LICENSE.md in the project root for more information
*-------------------------------------------------------------------------------------------*/
import { ChangeDetectorRef, Component, ElementRef, forwardRef, Input, QueryList, Renderer2, ViewChildren } from '@angular/core';
import { LocalizationService } from '@progress/kendo-angular-l10n';
import { filterAddExpressionIcon, filterAddGroupIcon, xIcon } from '@progress/kendo-svg-icons';
import { BaseFilterRowComponent } from './base-filter-row.component';
import { FilterService } from './filter.service';
import { NavigationService } from './navigation.service';
import { FilterItem, getKeyByValue, localizeOperators, logicOperators, selectors } from './util';
import { FilterExpressionComponent } from './filter-expression.component';
import { ButtonComponent } from '@progress/kendo-angular-buttons';
import { NgFor, NgClass, NgIf } from '@angular/common';
import * as i0 from "@angular/core";
import * as i1 from "./filter.service";
import * as i2 from "./navigation.service";
import * as i3 from "@progress/kendo-angular-l10n";
/**
* @hidden
*/
export class FilterGroupComponent extends BaseFilterRowComponent {
filterService;
cdr;
static ngAcceptInputType_currentItem;
/**
* @hidden
*/
xIcon = xIcon;
/**
* @hidden
*/
filterAddGroupIcon = filterAddGroupIcon;
/**
* @hidden
*/
filterAddExpressionIcon = filterAddExpressionIcon;
_filterItems;
get filterItems() {
return this._filterItems.toArray();
}
/**
* @hidden
*/
handleExpressionValueChange(isRemoveOperation) {
if (isRemoveOperation) {
// due to tracking by index, the filters should first be set to [] so that all rerender afterwards
const filtersCopy = this.currentItem.filters;
this.currentItem.filters = [];
this.cdr.detectChanges();
this.currentItem.filters = filtersCopy;
}
this.valueChange.emit(isRemoveOperation);
}
currentItem = {
logic: 'or',
filters: []
};
/**
* @hidden
*/
trackByFunction = (index) => {
return index;
};
operators = [];
localizationSubscription;
constructor(filterService, cdr, element, navigationService, localization, renderer) {
super(element, navigationService, localization, renderer);
this.filterService = filterService;
this.cdr = cdr;
}
ngOnInit() {
this.operators = this.getLogicOperators();
this.localizationSubscription = this.localization.changes.subscribe(() => {
this.operators = this.getLogicOperators();
this.cdr.detectChanges();
});
}
ngOnDestroy() {
if (this.localizationSubscription) {
this.localizationSubscription.unsubscribe();
}
}
getLogicOperators() {
return localizeOperators(logicOperators)(this.localization);
}
getOperator(operatorValue) {
return this.messageFor(getKeyByValue(logicOperators, operatorValue));
}
selectedChange(logicOperator) {
if (this.currentItem.logic !== logicOperator) {
this.currentItem.logic = logicOperator;
this.valueChange.emit();
}
}
addFilterExpression() {
this.filterService.addFilterExpression(this.currentItem);
this.valueChange.emit();
}
addFilterGroup() {
this.filterService.addFilterGroup(this.currentItem);
this.valueChange.emit();
}
removeFilterGroup() {
this.filterService.remove(this.currentItem, this.index);
this.cdr.detectChanges();
this.valueChange.emit(true);
}
onMouseDown(event) {
const toolbarItemElement = Array.from(event.target.closest(selectors.kendoToolbar).children).indexOf(event.target.closest(selectors.kendoFilterToolbarItem));
const buttonElement = Array.from(event.target.closest(selectors.kendoToolbar).children).indexOf(event.target.closest(selectors.kendoFilterToolbarButton));
let index = (toolbarItemElement > -1 ? toolbarItemElement : buttonElement) + 1;
if (event.target.closest(selectors.andButton)) {
index = 0;
}
if (event.target.closest(selectors.orButton)) {
index = 1;
}
this.navigationService.currentToolbarItemChildrenIndex = index;
this.navigationService.isFilterNavigationActivated = true;
const elementToFocus = this.navigationService.flattenFilterItems[this.itemNumber].focusableChildren[index];
this.navigationService.isFilterExpressionComponentFocused = false;
this.navigationService.currentToolbarItemIndex = this.itemNumber;
this.navigationService.focusCurrentElement(elementToFocus, true);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", 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 });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: FilterGroupComponent, isStandalone: true, selector: "kendo-filter-group", inputs: { currentItem: "currentItem" }, providers: [{
provide: FilterItem,
useExisting: forwardRef(() => FilterGroupComponent)
}], viewQueries: [{ propertyName: "_filterItems", predicate: FilterItem, descendants: true }], usesInheritance: true, ngImport: i0, template: `
<div class="k-filter-toolbar">
<div class="k-toolbar k-toolbar-md k-toolbar-solid" role="toolbar" [attr.aria-label]="messageFor('filterToolbarAriaLabel')" (mousedown)="onMouseDown($event)">
<div class="k-toolbar-button-group k-button-group k-button-group-solid" role="group">
<button
tabindex="-1"
*ngFor="let operator of operators"
kendoButton
class="k-toolbar-button"
[ngClass]="{'k-group-start': operator.value === 'and', 'k-group-end': operator.value === 'or'}"
[selected]="currentItem.logic === operator.value"
[attr.aria-pressed]="currentItem.logic === operator.value"
[title]="operator.text"
(click)="selectedChange(operator.value)"
>
{{getOperator(operator.value)}}
</button>
</div>
<button
kendoButton
class="k-toolbar-button"
tabindex="-1"
[title]="messageFor('addFilter')"
icon="filter-add-expression"
[svgIcon]="filterAddExpressionIcon"
(click)="addFilterExpression()">
{{messageFor('addFilter')}}
</button>
<button
kendoButton
class="k-toolbar-button"
tabindex="-1"
[title]="messageFor('addGroup')"
icon="filter-add-group"
[svgIcon]="filterAddGroupIcon"
(click)="addFilterGroup()">
{{messageFor('addGroup')}}
</button>
<button
kendoButton
class="k-toolbar-button"
tabindex="-1"
icon="x"
[svgIcon]="xIcon"
fillMode="flat"
[title]="messageFor('remove')"
(click)="removeFilterGroup()">
</button>
</div>
</div>
<ul class="k-filter-lines" role="group" *ngIf="currentItem.filters">
<ng-container *ngFor="let item of currentItem.filters; let i = index; trackBy: trackByFunction">
<li class="k-filter-item" role="treeitem" *ngIf="!item['filters']">
<kendo-filter-expression (valueChange)="handleExpressionValueChange($event)" [currentItem]="item" [index]="i">
</kendo-filter-expression>
</li>
<li class="k-filter-item" role="treeitem" *ngIf="item['filters']">
<kendo-filter-group
(valueChange)="valueChange.emit($event)"
[currentItem]="item"
[index]="i"
>
</kendo-filter-group>
</li>
</ng-container>
</ul>
`, isInline: true, dependencies: [{ kind: "component", type: FilterGroupComponent, selector: "kendo-filter-group", inputs: ["currentItem"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon", "primary", "look"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: FilterExpressionComponent, selector: "kendo-filter-expression", inputs: ["currentItem"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FilterGroupComponent, decorators: [{
type: Component,
args: [{
providers: [{
provide: FilterItem,
useExisting: forwardRef(() => FilterGroupComponent)
}],
selector: 'kendo-filter-group',
template: `
<div class="k-filter-toolbar">
<div class="k-toolbar k-toolbar-md k-toolbar-solid" role="toolbar" [attr.aria-label]="messageFor('filterToolbarAriaLabel')" (mousedown)="onMouseDown($event)">
<div class="k-toolbar-button-group k-button-group k-button-group-solid" role="group">
<button
tabindex="-1"
*ngFor="let operator of operators"
kendoButton
class="k-toolbar-button"
[ngClass]="{'k-group-start': operator.value === 'and', 'k-group-end': operator.value === 'or'}"
[selected]="currentItem.logic === operator.value"
[attr.aria-pressed]="currentItem.logic === operator.value"
[title]="operator.text"
(click)="selectedChange(operator.value)"
>
{{getOperator(operator.value)}}
</button>
</div>
<button
kendoButton
class="k-toolbar-button"
tabindex="-1"
[title]="messageFor('addFilter')"
icon="filter-add-expression"
[svgIcon]="filterAddExpressionIcon"
(click)="addFilterExpression()">
{{messageFor('addFilter')}}
</button>
<button
kendoButton
class="k-toolbar-button"
tabindex="-1"
[title]="messageFor('addGroup')"
icon="filter-add-group"
[svgIcon]="filterAddGroupIcon"
(click)="addFilterGroup()">
{{messageFor('addGroup')}}
</button>
<button
kendoButton
class="k-toolbar-button"
tabindex="-1"
icon="x"
[svgIcon]="xIcon"
fillMode="flat"
[title]="messageFor('remove')"
(click)="removeFilterGroup()">
</button>
</div>
</div>
<ul class="k-filter-lines" role="group" *ngIf="currentItem.filters">
<ng-container *ngFor="let item of currentItem.filters; let i = index; trackBy: trackByFunction">
<li class="k-filter-item" role="treeitem" *ngIf="!item['filters']">
<kendo-filter-expression (valueChange)="handleExpressionValueChange($event)" [currentItem]="item" [index]="i">
</kendo-filter-expression>
</li>
<li class="k-filter-item" role="treeitem" *ngIf="item['filters']">
<kendo-filter-group
(valueChange)="valueChange.emit($event)"
[currentItem]="item"
[index]="i"
>
</kendo-filter-group>
</li>
</ng-container>
</ul>
`,
standalone: true,
imports: [NgFor, ButtonComponent, NgClass, NgIf, FilterExpressionComponent]
}]
}], ctorParameters: function () { return [{ type: i1.FilterService }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }, { type: i2.NavigationService }, { type: i3.LocalizationService }, { type: i0.Renderer2 }]; }, propDecorators: { _filterItems: [{
type: ViewChildren,
args: [FilterItem]
}], currentItem: [{
type: Input
}] } });