@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
JavaScript
/**-----------------------------------------------------------------------------------------
* 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
}] });