UNPKG

@progress/kendo-angular-grid

Version:

Kendo UI Grid for Angular - high performance data grid with paging, filtering, virtualization, CRUD, and more.

222 lines (221 loc) 11.5 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 { ColumnComponent } from '../columns/column.component'; import { isPresent } from '@progress/kendo-angular-common'; import { ContextService } from './provider.service'; import { groupBy } from '@progress/kendo-data-query'; import * as i0 from "@angular/core"; import * as i1 from "./provider.service"; /** * @hidden */ export class ClipboardService { contextService; targetColField; targetRowIndex; constructor(contextService) { this.contextService = contextService; } createClipboardData(data, columns, options) { let result = { gridItems: [], dataString: '' }; const fieldCols = columns.flatMap(c => c instanceof ColumnComponent && isPresent(c.field) ? [c] : []); const clipboardData = { items: [], dataStrings: [] }; const colFields = fieldCols.map(c => c.field); if (options.wholeRow) { this.targetColField = fieldCols[0]?.field; this.targetRowIndex = data[0].dataRowIndex; data.forEach(item => { clipboardData.items.push({ dataItem: { ...item.dataItem }, fields: colFields }); clipboardData.dataStrings.push(this.itemToString(item.dataItem, fieldCols)); }); result = { gridItems: options.operationType === 'cut' ? clipboardData.items.map(item => { item.fields.forEach(field => item.dataItem[field] = null); return item; }) : [...clipboardData.items], dataString: options.copyHeaders ? this.addHeaders(clipboardData.dataStrings.join(`\r\n`), fieldCols) : clipboardData.dataStrings.join(`\n`) }; } else { if (options.target === 'selection') { const { tabular, groups } = this.groupSelection(); const selectionDirective = this.contextService.grid.selectionDirective; const colIdentifier = selectionDirective.columnKey; if (tabular) { const selectionKeys = groups[0].items.map(item => item.columnKey); const selectedFieldCols = columns.flatMap((c, i) => (c instanceof ColumnComponent && c.field) && isPresent((selectionKeys.find(k => typeof colIdentifier === 'function' ? k === colIdentifier(c, i) : k === i))) ? [c] : []); const selectedColFields = selectedFieldCols.map(c => c.field); this.targetColField = selectedColFields[0]; result.dataString = data.flatMap(item => { const itemString = this.itemToString(item.dataItem, selectedFieldCols); const existingItem = isPresent(itemString); if (!isPresent(this.targetRowIndex) && isPresent(itemString)) { this.targetRowIndex = item.dataRowIndex; } if (options.operationType === 'cut') { selectedColFields.forEach(f => item.dataItem[f] = null); } result.gridItems.push({ dataItem: item.dataItem, fields: selectedColFields }); return existingItem ? [itemString] : []; }).join(`\r\n`); if (options.copyHeaders) { result.dataString = this.addHeaders(result.dataString, selectedFieldCols); } } else { // split per row (uneven rows) const rowIdentifier = selectionDirective.selectionKey; result.dataString = data.flatMap(item => { // determine cols per item const key = rowIdentifier ? typeof rowIdentifier === 'string' ? item.dataItem[rowIdentifier] : rowIdentifier({ index: item.dataRowIndex, dataItem: item.dataItem }) : item.dataRowIndex; const selectionKeys = groups.find(gr => gr.value === key).items.map(item => item.columnKey); const selectedFieldCols = columns.flatMap((c, i) => (c instanceof ColumnComponent && c.field) && isPresent(selectionKeys.find(k => typeof colIdentifier === 'function' ? k === colIdentifier(c, i) : k === i)) ? [c] : []); const selectedColFields = selectedFieldCols.map(c => c.field); if (!this.targetColField) { this.targetColField = selectedColFields[0]; } const itemString = this.itemToString(item.dataItem, selectedFieldCols); const existingItem = isPresent(itemString); if (!isPresent(this.targetRowIndex) && existingItem) { this.targetRowIndex = item.dataRowIndex; } if (existingItem) { if (options.operationType === 'cut') { selectedColFields.forEach(f => item.dataItem[f] = null); } result.gridItems.push({ dataItem: item.dataItem, fields: selectedColFields }); } return existingItem ? options.copyHeaders ? [this.addHeaders(itemString, selectedFieldCols)] : [itemString] : []; }).join(`\r\n`); } } else { const item = data[0]; const col = columns[item.colIndex]; const colField = col.field; const title = col.title; const copiedData = item.dataItem[colField]; this.targetRowIndex = item.dataRowIndex; this.targetColField = colField; if (options.operationType === 'cut' && colField) { item.dataItem[colField] = null; } result = { gridItems: [{ dataItem: item.dataItem, fields: colField ? [colField] : [] }], dataString: options.copyHeaders ? [title || colField, copiedData].join(`\r\n`) : colField ? copiedData : `` }; } } return result; } getGridData(data, columns, targetType, targetRowIndex, options) { const separator = data.includes(`\r\n`) ? `\r\n` : data.includes(`\n`) ? `\n` : null; const dataRows = separator ? data.split(separator).filter(rowData => rowData.length) : [data]; this.targetRowIndex = targetRowIndex; if (targetType === 'activeCell') { if (options.wholeRow) { this.targetColField = columns.find(c => c instanceof ColumnComponent && c.field)?.field; } else { const activeCellIndex = this.contextService.grid.activeCell.colIndex; for (let i = 0; i < columns.length; i++) { const col = columns[i]; if (col instanceof ColumnComponent && col.field && i >= activeCellIndex) { this.targetColField = col.field; break; } } } } else { if (options.wholeRow || !options.isCellSelection) { this.targetColField = (columns.filter(c => c instanceof ColumnComponent && c.field))[0]['field']; } else { const { groups } = this.groupSelection(); const selectionDirective = this.contextService.grid.selectionDirective; const colIdentifier = selectionDirective.columnKey; const visibleCols = columns.filter(c => c.isVisible); const selectionKeys = groups[0].items.map(item => item.columnKey); const selectedFieldCols = visibleCols.flatMap((c, i) => (c instanceof ColumnComponent && c.field) && isPresent(selectionKeys.find(k => typeof colIdentifier === 'function' ? k === colIdentifier(c, i) : k === i)) ? [c] : []); const selectedColFields = selectedFieldCols.map(c => c.field); this.targetColField = selectedColFields[0]; } } const items = dataRows.map(rowString => { const cells = rowString.includes(`\t`) ? rowString.split(`\t`) : [rowString]; const colFields = columns.flatMap(c => (c instanceof ColumnComponent) && c.field ? [c.field] : []); const targetColFieldIndex = colFields.indexOf(this.targetColField); const affectedFields = colFields.slice(targetColFieldIndex, targetColFieldIndex + cells.length); const item = {}; colFields.slice(targetColFieldIndex, targetColFieldIndex + cells.length).forEach((colField, index) => item[colField] = cells[index]); return { dataItem: item, fields: affectedFields }; }); return items; } itemToString = (item, cols) => { if (!cols.length) { return null; } return cols.map(col => item[col.field]).join(`\t`); }; groupSelection() { const selection = this.contextService.grid.selection; const groups = groupBy(selection, [{ field: 'itemKey' }]) .map(gr => { gr.items.sort((a, b) => a.columnKey - b.columnKey); return gr; }); for (let i = 1; i < groups.length; i++) { if (!this.areEqual(groups[i].items, groups[i - 1].items)) { return { tabular: false, groups }; } } return { tabular: true, groups }; } areEqual(arr1, arr2) { if (arr1.length !== arr2.length) { return false; } for (let i = 0; i < arr1.length; i++) { if (arr1[i].columnKey !== arr2[i].columnKey) { return false; } } return true; } addHeaders(initialData, cols) { const headersRowData = cols.map(c => c.title || c.field).join(`\t`); return `${headersRowData}\r\n${initialData}`; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ClipboardService, deps: [{ token: i1.ContextService }], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ClipboardService }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ClipboardService, decorators: [{ type: Injectable }], ctorParameters: function () { return [{ type: i1.ContextService }]; } });