UNPKG

@progress/kendo-angular-dropdowns

Version:

A wide variety of native Angular dropdown components including AutoComplete, ComboBox, DropDownList, DropDownTree, MultiColumnComboBox, MultiSelect, and MultiSelectTree

251 lines (250 loc) 7.83 kB
/**----------------------------------------------------------------------------------------- * Copyright © 2025 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the project root for more information *-------------------------------------------------------------------------------------------*/ import { Injectable } from '@angular/core'; import { isPresent, hasProps, getter, filterAndMap } from './util'; import * as i0 from "@angular/core"; /** * @hidden */ export class DataService { grouped = false; groupIndices = []; view; _data; _flatData; set data(data) { this._data = data; this.grouped = this.isGrouped(data); if (this.grouped) { this.groupIndices = this.getGroupIndices(data); this._flatData = this.flatten(data); } } get data() { if (this.grouped) { return this._flatData; } return this._data; } /** * @hidden * Used to get the actual items count, i.e. excluding the header items in case of grouping. */ get itemsCount() { if (!isPresent(this.data) || this.data.length === 0) { return 0; } const items = this.grouped ? this._flatData.filter(item => !item.header) : this.data; return items.length; } /** * @hidden * Used to determine if the component received grouped data. */ isGrouped(data) { // GroupResult { aggregates: AggregateResult, field: string, items: object[], value: any } // https://www.telerik.com/kendo-angular-ui/components/dataquery/api/GroupResult/ return (isPresent(data) && data.length !== 0) && isPresent(data[0]) && hasProps(data[0], ['aggregates', 'field', 'items', 'value']); } /** * @hidden * Used to calculate the last item index of each group. */ getGroupIndices(data) { const groupIndices = []; for (let i = 0; i <= data.length - 1; i++) { groupIndices[i] = (groupIndices[i - 1] || 0) + data[i].items.length; } return groupIndices; } /** * @hidden * Used to get a flat array containing all items matching certain criteria. */ filter(predicate) { let result = []; if (this.isGrouped(this.data)) { for (let i = 0; i <= this.groupIndices.length - 1; i++) { const matches = this.data[i].items.filter(predicate); if (matches) { result = result.concat(matches); } } } else { result = this.data.filter(predicate); } return result; } /** * @hidden * Used to get the index of a given data item. */ indexOf(item, startFrom = 0) { let predicate = (element) => { return element === item; }; if (this.grouped) { predicate = (element) => { return element.value === item; }; } return this.findIndex(predicate, startFrom); } /** * @hidden * Used to get the index of a data item based on an expression. */ findIndex(predicate, startFrom = 0) { let index = -1; if (this.grouped) { const data = this._flatData.filter(item => !item.header && item.offsetIndex >= startFrom); index = data.findIndex(predicate); index = data[index] ? data[index].offsetIndex : -1; } else { const data = this.data.slice(startFrom); const itemIndex = data.findIndex(predicate); index = itemIndex !== -1 ? itemIndex + startFrom : -1; } return index; } /** * @hidden * Used to get the closest group header prior to an item index. */ closestGroup(index) { for (let i = index; i >= 0; i--) { if (this._flatData[i].header) { return this._flatData[i]; } } } /** * @hidden * Used to get the first item matching the criteria. */ find(predicate) { const index = this.findIndex(predicate); return this.itemAt(index); } /** * @hidden * Used to get the true index in a flattened data array. */ flatIndex(index) { if (this.itemsCount === 0) { return -1; } if (this.grouped) { const match = this._flatData.find((item) => !item.header && item.offsetIndex === index); if (match) { return match.index; } } else { return index; } return -1; } /** * @hidden * Used to get the item at the provided index. */ itemAt(index) { let dataItem; if (this.itemsCount === 0) { return dataItem; } if (this.grouped) { const match = this._flatData.find((item) => !item.header && item.offsetIndex === index); if (match) { dataItem = match.value; } } else { dataItem = this.data[index]; } return dataItem; } /** * @hidden * Used to get the group at the provided index. */ groupAt(index) { if (this.itemsCount === 0 || !this.isGrouped) { return; } return this._flatData.find((item) => item.header && item.index === index); } /** * @hidden * Used to get all group items indices. */ groupItemsIndices() { if (this.isGrouped) { return filterAndMap(this.data, item => item.header, mappedItem => mappedItem.index); } return []; } /** * @hidden * Used to get the field by which the data is grouped. */ groupField() { if (this.itemsCount === 0 || !this.isGrouped) { return null; } return this._data[0].field; } /** * @hidden * Used to get the group to which a dataItem belongs. */ itemGroup(item) { if (!item || this.itemsCount === 0 || !this.isGrouped) { return; } const fieldName = this.groupField(); if (fieldName) { return getter(item, fieldName); } } flatten(data, group = undefined, offset = 0, groupIndex = 0) { let flat = []; if (isPresent(group)) { flat.push({ header: true, groupIndex: groupIndex, index: groupIndex + offset, offsetIndex: groupIndex, value: group }); } for (let i = 0; i < data.length; i++) { let result = []; if (data[i].items) { result = this.flatten(data[i].items, data[i].value, offset, i); offset = offset + data[i].items.length; } else { result.push({ header: false, groupIndex: groupIndex, index: groupIndex + offset + i + 1, offsetIndex: offset + i, value: data[i] }); } flat = flat.concat(result); } return flat; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DataService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DataService }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DataService, decorators: [{ type: Injectable }] });