@progress/kendo-angular-treelist
Version:
Kendo UI TreeList for Angular - Display hierarchical data in an Angular tree grid view that supports sorting, filtering, paging, and much more.
224 lines (223 loc) • 8.7 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, Input, Output, EventEmitter } from '@angular/core';
import { TreeListComponent } from '../treelist.component';
import { getter } from '@progress/kendo-common';
import { isString } from '../utils';
import { createState, RowSelectionState } from './selection-state';
import { SelectionService } from './selection.service';
import * as i0 from "@angular/core";
import * as i1 from "../treelist.component";
import * as i2 from "./selection.service";
const defaultColumnKeyGetter = (_column, columnIndex) => columnIndex;
/**
* A directive which controls the selection state. [See example](slug:selection_treelist).
*
* @example
* ```html
* <kendo-treelist
* [kendoTreeListSelectable]="{ mode: 'row' }"
* [selectedItems]="selectedItems">
* <kendo-treelist-column field="name" title="Name"></kendo-treelist-column>
* <kendo-treelist-column field="age" title="Age"></kendo-treelist-column>
* </kendo-treelist>
* ```
* @remarks
* Applied to: {@link TreeListComponent}.
*/
export class SelectableDirective {
treelist;
selectionService;
/**
* @hidden
*/
set selectable(value) {
if (typeof value === 'object') { // add method to normalize this
this._settings = value;
}
else {
this._settings = {
enabled: value
};
}
this.state = createState(this._settings);
this.state.fromArray(this._selectedItems || []);
if (this._settings.enabled !== false) {
this.treelist.isSelected = this._settings.mode === 'cell' ? this.cellSelected : this.rowSelected;
this.subscribeSelection();
}
else {
this.treelist.isSelected = () => false;
this.unsubscribeSelection();
}
this.treelist.updateView();
}
/**
* Specifies the selected items.
*/
set selectedItems(value) {
if (!value) {
this.state.clear();
}
else if (value !== this.lastChange) {
this.state.fromArray(value);
this.treelist.updateView();
}
this._selectedItems = value;
const currentValue = value || [];
const previousState = this.selectionService.selectAllCheckedState;
if (currentValue.length > 0 && currentValue.length === this.treelist.view.total) {
this.selectionService.selectAllCheckedState = true;
}
else if (currentValue.length === 0) {
this.selectionService.selectAllCheckedState = false;
}
else {
this.selectionService.selectAllCheckedState = 'indeterminate';
}
if (previousState !== this.selectionService.selectAllCheckedState) {
this.selectionService.selectAllCheckedStateChange.next(this.selectionService.selectAllCheckedState);
}
}
/**
* Fires when the selected items are changed.
*/
selectedItemsChange = new EventEmitter();
/**
* The field name or a function that specify the dataItems key.
*/
set itemKey(value) {
if (isString(value)) {
this._keyGetter = getter(String(value));
}
else {
this._keyGetter = value;
}
}
/**
* The field name or a function that specify the columns key.
*/
set columnKey(value) {
if (isString(value)) {
this._columnKeyGetter = getter(String(value));
}
else if (value) {
this._columnKeyGetter = value;
}
}
get keyGetter() {
return this._keyGetter || this.treelist.idGetter;
}
get columnKeyGetter() {
return this._columnKeyGetter || defaultColumnKeyGetter;
}
subscriptions;
state = new RowSelectionState();
_settings;
lastChange;
_columnKeyGetter;
_keyGetter;
_selectedItems = [];
constructor(treelist, selectionService) {
this.treelist = treelist;
this.selectionService = selectionService;
this.cellSelected = this.cellSelected.bind(this);
this.rowSelected = this.rowSelected.bind(this);
this.selectionChange = this.selectionChange.bind(this);
this.updateColumnIndices = this.updateColumnIndices.bind(this);
this.treelist.selectable = this.selectable = true;
}
ngOnDestroy() {
this.unsubscribeSelection();
}
/**
* @hidden
*/
cellSelected(dataItem, column, columnIndex) {
return this.state.has(this.keyGetter(dataItem), this.columnKeyGetter(column, columnIndex));
}
/**
* @hidden
*/
rowSelected(dataItem) {
return this.state.has(this.keyGetter(dataItem));
}
selectionChange({ action, items }) {
if (action === 'select' || action === 'add') {
if (action === 'select') {
this.state.clear();
}
items.forEach(item => {
this.state.add(this.keyGetter(item.dataItem), this.columnKeyGetter(item.column, item.columnIndex));
});
}
else {
items.forEach(item => {
this.state.remove(this.keyGetter(item.dataItem), this.columnKeyGetter(item.column, item.columnIndex));
});
}
this.emitSelectedItemsChange();
}
emitSelectedItemsChange() {
this.selectionService.state = this.lastChange = this.state.toArray();
this.selectedItemsChange.emit(this.lastChange);
}
subscribeSelection() {
this.unsubscribeSelection();
this.subscriptions = this.treelist.selectionChange.subscribe(this.selectionChange);
if (this._settings.mode === 'cell') {
this.subscriptions.add(this.treelist.columnOrderChange.subscribe(this.updateColumnIndices));
this.subscriptions.add(this.treelist.columnLockedChange.subscribe(this.updateColumnIndices));
}
}
unsubscribeSelection() {
if (this.subscriptions) {
this.subscriptions.unsubscribe();
this.subscriptions = null;
}
}
updateColumnIndices() {
if (!this._columnKeyGetter) {
const changes = new Map();
const currentIndices = [];
this.leafColumns.forEach((column) => {
currentIndices.push(column);
});
this.treelist.columnsContainer.refresh();
const leafColumns = this.leafColumns;
currentIndices.forEach((column, index) => {
if (column !== leafColumns[index]) {
changes.set(index, leafColumns.indexOf(column));
}
});
if (changes.size && this.state.updateColumKeys(changes)) {
this.emitSelectedItemsChange();
}
}
}
get leafColumns() {
return this.treelist.lockedLeafColumns.toArray().concat(this.treelist.nonLockedLeafColumns.toArray());
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SelectableDirective, deps: [{ token: i1.TreeListComponent }, { token: i2.SelectionService }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.14", type: SelectableDirective, isStandalone: true, selector: "[kendoTreeListSelectable]", inputs: { selectable: "selectable", selectedItems: "selectedItems", itemKey: "itemKey", columnKey: "columnKey" }, outputs: { selectedItemsChange: "selectedItemsChange" }, exportAs: ["kendoTreeListSelectable"], ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SelectableDirective, decorators: [{
type: Directive,
args: [{
exportAs: 'kendoTreeListSelectable',
selector: '[kendoTreeListSelectable]',
standalone: true
}]
}], ctorParameters: () => [{ type: i1.TreeListComponent }, { type: i2.SelectionService }], propDecorators: { selectable: [{
type: Input
}], selectedItems: [{
type: Input
}], selectedItemsChange: [{
type: Output
}], itemKey: [{
type: Input
}], columnKey: [{
type: Input
}] } });