@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.
175 lines (174 loc) • 5.89 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, EventEmitter, NgZone } from '@angular/core';
import { isPresent, isColumnEditable } from '../utils';
import { CellCloseEvent } from './cell-close-event';
import { Subject } from 'rxjs';
import { switchMap, take } from 'rxjs/operators';
import * as i0 from "@angular/core";
const identity = item => item;
/**
* @hidden
*/
export class EditService {
ngZone;
changes = new EventEmitter();
changed;
get newItemGroup() {
return this.newItem ? this.newItem.group : null;
}
newItem;
idGetter = identity;
// Maps IDs to edited rows
edited = new Map();
keepEditCell = false;
keepCellTimeout;
column;
closingCell = false;
changedSource = new Subject();
constructor(ngZone) {
this.ngZone = ngZone;
this.changed = this.changedSource.asObservable().pipe(switchMap(() => this.ngZone.onStable.asObservable().pipe(take(1))));
}
editRow(dataItem, group = undefined) {
this.edited.set(this.idGetter(dataItem), {
group,
item: dataItem
});
this.onChanged();
}
addRow(parent, group) {
this.newItem = { parent, group, dataItem: group ? group.value : null };
this.onChanged();
}
editCell(item, column, group) {
if (!isColumnEditable(column, group)) {
return;
}
this.preventCellClose();
if (!this.closeCell()) {
this.editRow(item, group);
this.column = column;
this.onChanged();
}
}
isEditing() {
return this.edited.size > 0;
}
isEdited(dataItem) {
return (this.newItem && this.newItem.dataItem === dataItem) ||
this.edited.has(this.idGetter(dataItem));
}
isEditingCell() {
return isPresent(this.column);
}
isEditingColumn(column) {
return this.column === column;
}
isEditedColumn(column) {
return !this.column || this.column === column;
}
hasNew(parent) {
return Boolean(this.newItem && ((!this.newItem.parent && !parent) ||
this.idGetter(this.newItem.parent) === this.idGetter(parent)));
}
get newDataItem() {
if (this.newItem) {
return this.newItem.group.value;
}
}
close(item, isNew) {
if (isNew) { // parent
this.newItem = undefined;
return;
}
this.edited.delete(this.idGetter(item));
delete this.column;
this.onChanged();
}
closeCell(originalEvent) {
if (this.column && !this.closingCell) {
return this.ngZone.run(() => {
const { item, group } = this.first;
const args = new CellCloseEvent({
column: this.column,
formGroup: group,
originalEvent: originalEvent,
dataItem: item
});
this.closingCell = true;
this.changes.emit(args);
this.closingCell = false;
if (!args.isDefaultPrevented()) {
this.cancelCell();
}
return args.isDefaultPrevented();
});
}
}
cancelCell() {
if (this.column) {
this.edited.clear();
this.column = null;
this.onChanged();
}
}
shouldCloseCell() {
return this.column && !this.keepEditCell;
}
preventCellClose() {
this.ngZone.runOutsideAngular(() => {
window.clearTimeout(this.keepCellTimeout);
this.keepEditCell = true;
this.keepCellTimeout = window.setTimeout(() => {
this.keepEditCell = false;
}, 0);
});
}
context(dataItem) {
return this.edited.get(this.idGetter(dataItem));
}
beginEdit(item) {
this.changes.emit({ action: 'edit', dataItem: item });
}
beginAdd(parent) {
this.changes.emit({ action: 'add', parent });
}
endEdit(dataItem, isNew) {
const formGroup = isNew ? this.newItemGroup : this.context(dataItem).group;
this.changes.emit({ action: 'cancel', dataItem, formGroup, isNew });
}
save(item, isNew) {
const args = { action: 'save', isNew: isNew };
if (isNew) {
args.parent = this.newItem.parent;
args.formGroup = this.newItem.group;
args.dataItem = item;
}
else {
args.dataItem = item;
args.formGroup = this.context(item).group;
}
this.changes.emit(args);
}
remove(dataItem, parent) {
this.changes.emit({ action: 'remove', dataItem, parent });
}
onChanged() {
this.ngZone.runOutsideAngular(() => {
this.changedSource.next();
});
}
get first() {
if (this.isEditing()) {
return this.edited.values().next().value;
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: EditService, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: EditService });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: EditService, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: i0.NgZone }]; } });