@progress/kendo-angular-grid
Version:
Kendo UI Grid for Angular - high performance data grid with paging, filtering, virtualization, CRUD, and more.
220 lines (219 loc) • 9.99 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 { Directive, NgZone, Renderer2 } from '@angular/core';
import { ToolBarButtonComponent } from '@progress/kendo-angular-toolbar';
import { Subscription } from 'rxjs';
import { filterIcon } from '@progress/kendo-svg-icons';
import { PopupService } from '@progress/kendo-angular-popup';
import { ContextService } from '../../../common/provider.service';
import { closest, isDocumentAvailable, isPresent } from '@progress/kendo-angular-common';
import { ColumnInfoService } from '../../../common/column-info.service';
import { take } from 'rxjs/operators';
import { FilterService } from '../../../filtering/filter.service';
import { FilterToolWrapperComponent } from './filter-tool-wrapper.component';
import { AdaptiveGridService } from '../../../common/adaptiveness.service';
import * as i0 from "@angular/core";
import * as i1 from "@progress/kendo-angular-toolbar";
import * as i2 from "@progress/kendo-angular-popup";
import * as i3 from "../../../common/provider.service";
import * as i4 from "../../../filtering/filter.service";
import * as i5 from "../../../common/column-info.service";
import * as i6 from "../../../common/adaptiveness.service";
let incrementingId = 0;
/**
* Represents the toolbar tool for filtering columns of the Grid.
* Use this directive on any `kendo-toolbar-button` inside a ToolbarComponent in the Grid.
*
* When you click the toolbar button with this directive, the `filter` event is triggered.
*
* @example
* ```html
* <kendo-grid>
* <kendo-toolbar>
* <kendo-toolbar-button text="Filter" kendoGridFilterTool></kendo-toolbar-button>
* </kendo-toolbar>
* </kendo-grid>
* ```
* @remarks
* Applied to: {@link ToolBarButtonComponent}.
*/
export class FilterCommandToolbarDirective {
host;
popupService;
ctx;
filterService;
columnInfoService;
ngZone;
renderer;
adaptiveGridService;
popupRef;
nextId = incrementingId++;
toolSubs = new Subscription();
popupSubs;
actionSheetCloseSub;
removeClickListener;
/**
* @hidden
*/
isFilterApplied(filter) {
return isPresent(filter) && filter.filters?.length > 0;
}
constructor(host, popupService, ctx, filterService, columnInfoService, ngZone, renderer, adaptiveGridService) {
this.host = host;
this.popupService = popupService;
this.ctx = ctx;
this.filterService = filterService;
this.columnInfoService = columnInfoService;
this.ngZone = ngZone;
this.renderer = renderer;
this.adaptiveGridService = adaptiveGridService;
}
ngOnInit() {
this.toolSubs = this.host.click.subscribe(e => this.onClick(e));
this.toolSubs.add(this.filterService.changes.subscribe(filter => {
this.host.showBadge = this.isFilterApplied(filter);
}));
this.host.hasBadgeContainer = true;
this.host.showBadge = this.isFilterApplied(this.ctx.grid.filter);
const hasToolbarIcon = isPresent(this.host.toolbarOptions.icon) && this.host.toolbarOptions.icon !== '';
const hasOverflowIcon = isPresent(this.host.overflowOptions.icon) && this.host.overflowOptions.icon !== '';
const hasIcon = hasToolbarIcon && hasOverflowIcon;
const hasSvgIcon = isPresent(this.host.toolbarOptions.svgIcon) && isPresent(this.host.overflowOptions.svgIcon);
if (!hasIcon) {
this.host.icon = 'filter';
}
if (!hasSvgIcon) {
this.host.svgIcon = filterIcon;
}
}
ngAfterViewInit() {
if (!isPresent(this.host.text)) {
this.ngZone.onStable.pipe(take(1)).subscribe(() => {
this.host.text = this.ctx.localization.get(`filterToolbarToolText`);
});
}
this.buttonElement?.setAttribute('aria-haspopup', 'dialog');
this.buttonElement?.setAttribute('aria-expanded', 'false');
this.buttonElement?.setAttribute('title', this.ctx.localization.get('filterToolbarToolText'));
}
ngOnDestroy() {
if (this.toolSubs) {
this.toolSubs.unsubscribe();
}
if (this.popupSubs) {
this.popupSubs.unsubscribe();
}
if (this.popupRef) {
this.popupRef.close();
this.popupRef = null;
}
if (this.actionSheetCloseSub) {
this.actionSheetCloseSub.unsubscribe();
this.actionSheetCloseSub = null;
}
if (this.removeClickListener) {
this.removeClickListener();
this.removeClickListener = null;
}
}
onClick(e) {
e.preventDefault();
if (this.popupRef) {
this.closePopup();
return;
}
this.openPopup();
}
openPopup() {
const direction = this.ctx.localization.rtl ? 'right' : 'left';
if (this.ctx.grid.adaptiveMode === 'auto' && this.adaptiveGridService.windowSize !== 'large') {
if (!this.ctx.grid.isActionSheetExpanded) {
this.adaptiveGridService.viewType = 'filterToolbarTool';
this.ctx.grid.adaptiveRenderer.actionSheet.toggle(true);
this.host.selected = true;
this.actionSheetCloseSub = this.ctx.grid.adaptiveRenderer.actionSheet.collapse.subscribe(() => this.host.selected = false);
}
}
else {
this.popupRef = this.popupService.open({
anchor: this.buttonElement,
content: FilterToolWrapperComponent,
popupClass: 'k-grid-columnmenu-popup',
positionMode: 'absolute',
anchorAlign: { vertical: 'bottom', horizontal: direction },
popupAlign: { vertical: 'top', horizontal: direction }
});
this.adaptiveGridService.popupRef = this.popupRef;
this.setPopupAttributes();
this.host.selected = true;
this.ngZone.runOutsideAngular(() => {
if (!isDocumentAvailable()) {
return;
}
this.removeClickListener = this.renderer.listen('document', 'click', (e) => {
if (this.popupRef && !closest(e.target, node => node === this.popupRef.popupElement || node === this.buttonElement)) {
this.ngZone.run(() => {
this.closePopup();
});
}
});
});
this.popupSubs = this.popupRef.popup.instance.anchorViewportLeave.subscribe(() => {
this.popupSubs?.unsubscribe();
this.popupSubs = null;
this.closePopup();
});
this.initPopupProperties();
}
}
setPopupAttributes() {
const popupElement = this.popupRef.popupElement;
const popupId = `k-filter-tool-${this.nextId}-popup`;
const popupAriaElement = popupElement.querySelector('.k-popup');
this.renderer.setAttribute(popupElement, 'dir', this.ctx.localization.rtl ? 'rtl' : 'ltr');
this.renderer.setAttribute(popupAriaElement, 'id', popupId);
this.renderer.setAttribute(popupAriaElement, 'role', 'dialog');
this.buttonElement?.setAttribute('aria-expanded', 'true');
this.buttonElement?.setAttribute('aria-controls', popupId);
}
initPopupProperties() {
this.popupRef.content.instance.columnInfoService = this.columnInfoService;
this.popupRef.content.instance.ctx = this.ctx;
this.popupRef.content.instance.filterService = this.filterService;
this.popupRef.content.instance.hostButton = this.host;
this.popupSubs.add(this.popupRef.content.instance.close.subscribe(() => {
this.closePopup();
}));
}
closePopup() {
this.buttonElement?.setAttribute('aria-expanded', 'false');
this.buttonElement?.removeAttribute('aria-controls');
this.host.selected = false;
if (this.popupRef) {
this.popupRef.close();
this.popupRef = null;
}
if (this.popupSubs) {
this.popupSubs.unsubscribe();
this.popupSubs = null;
}
if (this.removeClickListener) {
this.removeClickListener();
this.removeClickListener = null;
}
}
get buttonElement() {
return this.host.getButton();
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FilterCommandToolbarDirective, deps: [{ token: i1.ToolBarButtonComponent }, { token: i2.PopupService }, { token: i3.ContextService }, { token: i4.FilterService }, { token: i5.ColumnInfoService }, { token: i0.NgZone }, { token: i0.Renderer2 }, { token: i6.AdaptiveGridService }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: FilterCommandToolbarDirective, isStandalone: true, selector: "[kendoGridFilterTool]", ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FilterCommandToolbarDirective, decorators: [{
type: Directive,
args: [{
selector: '[kendoGridFilterTool]',
standalone: true
}]
}], ctorParameters: function () { return [{ type: i1.ToolBarButtonComponent }, { type: i2.PopupService }, { type: i3.ContextService }, { type: i4.FilterService }, { type: i5.ColumnInfoService }, { type: i0.NgZone }, { type: i0.Renderer2 }, { type: i6.AdaptiveGridService }]; } });