UNPKG

@progress/kendo-angular-treeview

Version:
148 lines (147 loc) 6.31 kB
/**----------------------------------------------------------------------------------------- * Copyright © 2025 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the project root for more information *-------------------------------------------------------------------------------------------*/ import { anyChanged, isChanged } from '@progress/kendo-angular-common'; import { Directive, Input } from '@angular/core'; import { getter } from '@progress/kendo-common'; import { of } from 'rxjs'; import { compose } from './funcs'; import { DataBoundComponent } from './data-bound-component'; import { isBlank, isNullOrEmptyString, isPresent, isArrayWithAtLeastOneItem } from './utils'; import { FlatEditingService } from "./drag-and-drop/editing-services/flat-editing.service"; import { IndexBuilderService } from './index-builder.service'; import { FilteringBase } from './filtering-base'; import * as i0 from "@angular/core"; import * as i1 from "./data-bound-component"; const findChildren = (prop, nodes, value) => nodes.filter((x) => prop(x) === value); const indexBuilder = new IndexBuilderService(); const mapToTree = (currentLevelNodes, allNodes, parentIdField, idField, parent = null, parentIndex = '') => { if (!isArrayWithAtLeastOneItem(currentLevelNodes)) { return []; } return currentLevelNodes.map((node, idx) => { const index = indexBuilder.nodeIndex(idx.toString(), parentIndex); const wrapper = { dataItem: node, index, parent, visible: true }; wrapper.children = mapToTree(findChildren(getter(parentIdField), allNodes || [], getter(idField)(node)), allNodes, parentIdField, idField, wrapper, index); return wrapper; }); }; /** * A directive which encapsulates the retrieval of the child nodes. */ export class FlatDataBindingDirective extends FilteringBase { component; /** * The nodes which will be displayed by the TreeView. */ set nodes(nodes) { // Needs to be a setter so that it can be accessed via `super` call (typescript v5) this._nodes = nodes; } get nodes() { return this._nodes; } _nodes; /** * Represents the parent field whose value will be matched with the parent node. */ parentIdField; /** * Represents the unique field which identifies a node. */ idField; /** * @hidden */ loadOnDemand = true; /** * @hidden * A callback which determines whether a TreeView node should be rendered as hidden. */ set isVisible(fn) { this.component.isVisible = fn; } /** * @hidden */ originalData = []; constructor(component) { super(component); this.component = component; this.component.isVisible = (node) => this.visibleNodes.has(node); } /** * @hidden */ ngOnInit() { if (isPresent(this.parentIdField) && isPresent(this.idField)) { const fetchChildren = (node) => findChildren(getter(this.parentIdField), this.originalData || [], getter(this.idField)(node)); this.component.hasChildren = (node) => fetchChildren(node).length > 0; this.component.children = (node) => of(fetchChildren(node)); this.component.editService = new FlatEditingService(this); this.component.filterChange.subscribe(this.handleFilterChange.bind(this)); if (this.component.filter) { this.handleFilterChange(this.component.filter); } if (!this.loadOnDemand && isPresent(this.component.preloadChildNodes)) { this.component.preloadChildNodes(); } } } /** * @hidden */ ngOnChanges(changes) { if (isChanged('parentIdField', changes, false)) { this.nodes = this.originalData; this.updateNodes(this.originalData); } if (isChanged('nodes', changes, false)) { this.updateNodes(changes['nodes'].currentValue); } // should react to changes.loadOnDemand as well - should preload the data or clear the already cached items if (anyChanged(['nodes', 'loadOnDemand'], changes) && !this.loadOnDemand && isPresent(this.component.preloadChildNodes)) { this.component.preloadChildNodes(); } } /** * @hidden */ updateNodes(values) { this.originalData = values || []; if (!isNullOrEmptyString(this.parentIdField)) { const prop = getter(this.parentIdField); this.component.nodes = this.originalData.filter(compose(isBlank, prop)); this.filterData = mapToTree(this.component.nodes, this.originalData, this.parentIdField, this.idField); this.updateVisibleNodes(this.filterData); } else { this.component.nodes = this.originalData.slice(0); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlatDataBindingDirective, deps: [{ token: i1.DataBoundComponent }], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: FlatDataBindingDirective, isStandalone: true, selector: "[kendoTreeViewFlatDataBinding]", inputs: { nodes: "nodes", parentIdField: "parentIdField", idField: "idField", loadOnDemand: "loadOnDemand", isVisible: "isVisible" }, usesInheritance: true, usesOnChanges: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlatDataBindingDirective, decorators: [{ type: Directive, args: [{ selector: "[kendoTreeViewFlatDataBinding]", standalone: true }] }], ctorParameters: function () { return [{ type: i1.DataBoundComponent }]; }, propDecorators: { nodes: [{ type: Input }], parentIdField: [{ type: Input }], idField: [{ type: Input }], loadOnDemand: [{ type: Input }], isVisible: [{ type: Input }] } });