Skip to content

Commit 6679b67

Browse files
Merge pull request #9138 from IgniteUI/dTsvetkov/fiix-8819-11.1.x
fix(column-selection): allow to copy column values-11.1.x #8819
2 parents 3e27163 + 0474b95 commit 6679b67

File tree

6 files changed

+109
-23
lines changed

6 files changed

+109
-23
lines changed

projects/igniteui-angular/src/lib/grids/grid-base.directive.ts

Lines changed: 98 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -756,8 +756,8 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements
756756
* <igx-grid [columnHiding]="true" [showToolbar]="true" (columnVisibilityChanging)="visibilityChanging($event)"></igx-grid>
757757
* ```
758758
*/
759-
@Output()
760-
public columnVisibilityChanging = new EventEmitter<IColumnVisibilityChangingEventArgs>();
759+
@Output()
760+
public columnVisibilityChanging = new EventEmitter<IColumnVisibilityChangingEventArgs>();
761761

762762
/**
763763
* Emitted after column visibility is changed.
@@ -4550,7 +4550,7 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements
45504550
this.gridAPI.prepare_sorting_expression([sortingState], expression);
45514551
}
45524552

4553-
const eventArgs: ISortingEventArgs = {owner: this, sortingExpressions: sortingState, cancel: false };
4553+
const eventArgs: ISortingEventArgs = { owner: this, sortingExpressions: sortingState, cancel: false };
45544554
this.sorting.emit(eventArgs);
45554555

45564556
if (eventArgs.cancel) {
@@ -5587,6 +5587,11 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements
55875587
return this.extractDataFromColumnsSelection(source, formatters, headers);
55885588
}
55895589

5590+
public combineSelectedCellAndColumnData(columnData: any[], formatters = false, headers = false) {
5591+
const source = this.filteredSortedData;
5592+
return this.extractDataFromSelection(source, formatters, headers, columnData);
5593+
}
5594+
55905595
/**
55915596
* @hidden @internal
55925597
*/
@@ -5606,11 +5611,56 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements
56065611
* @internal
56075612
*/
56085613
public copyHandler(event) {
5609-
if (!this.clipboardOptions.enabled || this.crudService.cellInEditMode || (!isIE() && event.type === 'keydown')) {
5614+
const selectedColumns = this.gridAPI.grid.selectedColumns();
5615+
const columnData = this.getSelectedColumnsData(this.clipboardOptions.copyFormatters, this.clipboardOptions.copyHeaders);
5616+
const selectedData = this.getSelectedData(this.clipboardOptions.copyFormatters, this.clipboardOptions.copyHeaders);
5617+
5618+
let data = [];
5619+
let result;
5620+
5621+
if (event.code === 'KeyC' && (event.ctrlKey || event.metaKey) && event.currentTarget.className === 'igx-grid__thead-wrapper') {
5622+
if (selectedData.length) {
5623+
if (columnData.length === 0) {
5624+
result = this.prepareCopyData(event, selectedData);
5625+
} else {
5626+
data = this.combineSelectedCellAndColumnData(columnData, this.clipboardOptions.copyFormatters,
5627+
this.clipboardOptions.copyHeaders);
5628+
result = this.prepareCopyData(event, data[0], data[1]);
5629+
}
5630+
} else {
5631+
data = columnData;
5632+
result = this.prepareCopyData(event, data);
5633+
}
5634+
5635+
if (isIE()) {
5636+
(window as any).clipboardData.setData('Text', result);
5637+
return;
5638+
}
5639+
navigator.clipboard.writeText(result).then().catch(e => console.error(e));
5640+
} else if (!this.clipboardOptions.enabled || this.crudService.cellInEditMode || (!isIE() && event.type === 'keydown')) {
56105641
return;
5642+
} else {
5643+
if (selectedColumns.length) {
5644+
data = this.combineSelectedCellAndColumnData(columnData, this.clipboardOptions.copyFormatters,
5645+
this.clipboardOptions.copyHeaders);
5646+
result = this.prepareCopyData(event, data[0], data[1]);
5647+
} else {
5648+
data = selectedData;
5649+
result = this.prepareCopyData(event, data);
5650+
}
5651+
5652+
if (isIE()) {
5653+
(window as any).clipboardData.setData('Text', result);
5654+
return;
5655+
}
5656+
event.clipboardData.setData('text/plain', result);
56115657
}
5658+
}
56125659

5613-
const data = this.getSelectedData(this.clipboardOptions.copyFormatters, this.clipboardOptions.copyHeaders);
5660+
/**
5661+
* @hidden @internal
5662+
*/
5663+
public prepareCopyData(event, data, keys?) {
56145664
const ev = { data, cancel: false } as IGridClipboardEvent;
56155665
this.onGridCopy.emit(ev);
56165666

@@ -5619,24 +5669,20 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements
56195669
}
56205670

56215671
const transformer = new CharSeparatedValueData(ev.data, this.clipboardOptions.separator);
5622-
let result = transformer.prepareData();
5672+
let result = keys ? transformer.prepareData(keys) : transformer.prepareData();
56235673

56245674
if (!this.clipboardOptions.copyHeaders) {
56255675
result = result.substring(result.indexOf('\n') + 1);
56265676
}
56275677

5628-
if (isIE()) {
5629-
(window as any).clipboardData.setData('Text', result);
5630-
return;
5631-
}
5632-
56335678
event.preventDefault();
56345679

56355680
/* Necessary for the hiearachical case but will probably have to
56365681
change how getSelectedData is propagated in the hiearachical grid
56375682
*/
56385683
event.stopPropagation();
5639-
event.clipboardData.setData('text/plain', result);
5684+
5685+
return result;
56405686
}
56415687

56425688
/**
@@ -6735,10 +6781,12 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements
67356781
.sort((a, b) => a.index - b.index);
67366782
}
67376783

6738-
protected extractDataFromSelection(source: any[], formatters = false, headers = false): any[] {
6784+
protected extractDataFromSelection(source: any[], formatters = false, headers = false, columnData?: any[]): any[] {
67396785
let columnsArray: IgxColumnComponent[];
67406786
let record = {};
6741-
const selectedData = [];
6787+
let selectedData = [];
6788+
let keys = [];
6789+
const keysAndData = [];
67426790
const activeEl = this.selectionService.activeElement;
67436791
const totalItems = (this as any).totalItemCount ?? 0;
67446792
const isRemote = totalItems && totalItems > this.dataView.length;
@@ -6753,6 +6801,10 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements
67536801
selectionMap.push([activeEl.row, new Set<number>().add(activeEl.column)]);
67546802
}
67556803

6804+
if (columnData) {
6805+
selectedData = columnData;
6806+
}
6807+
67566808
// eslint-disable-next-line prefer-const
67576809
for (let [row, set] of selectionMap) {
67586810
row = this.paging ? row + (this.perPage * this.page) : row;
@@ -6769,15 +6821,45 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements
67696821
const value = source[row].ghostRecord ?
67706822
resolveNestedPath(source[row].recordRef, col.field) : resolveNestedPath(source[row], col.field);
67716823
record[key] = formatters && col.formatter ? col.formatter(value) : value;
6824+
if (columnData) {
6825+
if (!record[key]) {
6826+
record[key] = '';
6827+
}
6828+
record[key] = record[key].toString().concat('recordRow-' + row);
6829+
}
67726830
}
67736831
});
67746832
}
67756833
if (Object.keys(record).length) {
6776-
selectedData.push(record);
6834+
if (columnData) {
6835+
if (!keys.length) {
6836+
keys = Object.keys(columnData[0]);
6837+
}
6838+
for (const [key, value] of Object.entries(record)) {
6839+
if (!keys.includes(key)) {
6840+
keys.push(key);
6841+
}
6842+
let c: any = value;
6843+
const rowNumber = +c.split('recordRow-')[1];
6844+
c = c.split('recordRow-')[0];
6845+
record[key] = c;
6846+
const mergedObj = Object.assign(selectedData[rowNumber], record);
6847+
selectedData[rowNumber] = mergedObj;
6848+
}
6849+
} else {
6850+
selectedData.push(record);
6851+
}
67776852
}
67786853
record = {};
67796854
}
6780-
return selectedData;
6855+
6856+
if (keys.length) {
6857+
keysAndData.push(selectedData);
6858+
keysAndData.push(keys);
6859+
return keysAndData;
6860+
} else {
6861+
return selectedData;
6862+
}
67816863
}
67826864

67836865
protected getSelectableColumnsAt(index) {

projects/igniteui-angular/src/lib/grids/grid/grid-clipboard.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ describe('IgxGrid - Clipboard #grid', () => {
146146
data: grid.getSelectedData(true, true),
147147
cancel: true
148148
});
149-
expect(eventData).toEqual('');
149+
expect(eventData).toEqual('' || 'undefined');
150150
});
151151

152152
it('Copy when there is a cell in edit mode', fakeAsync(() => {

projects/igniteui-angular/src/lib/grids/grid/grid.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
</div>
2727

2828
<div class="igx-grid__thead">
29-
<div class="igx-grid__thead-wrapper" [class.igx-grid__tr--mrl]='hasColumnLayouts' role="rowgroup" (focus)="navigation.focusFirstCell()"
29+
<div class="igx-grid__thead-wrapper" (keydown.meta.c)="copyHandler($event)" (keydown.control.c)="copyHandler($event)" (copy)="copyHandler($event)" [class.igx-grid__tr--mrl]='hasColumnLayouts' role="rowgroup" (focus)="navigation.focusFirstCell()"
3030
[style.width.px]='calcWidth' tabindex="0" [attr.aria-activedescendant]="activeDescendant" (keydown)="navigation.headerNavigation($event)" (scroll)="preventHeaderScroll($event)" #theadRow>
3131
<div class="igx-grid__tr" role="row" [style.width.px]='calcWidth'>
3232
<span *ngIf="hasMovableColumns && draggedColumn && pinnedColumns.length <= 0"

projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<ng-container #toolbarOutlet></ng-container>
33

44
<div class="igx-grid__thead">
5-
<div class="igx-grid__thead-wrapper" tabindex="0" (focus)="navigation.focusFirstCell()" [attr.aria-activedescendant]="activeDescendant"
5+
<div class="igx-grid__thead-wrapper" (keydown.meta.c)="copyHandler($event)" (keydown.control.c)="copyHandler($event)" (copy)="copyHandler($event)" tabindex="0" (focus)="navigation.focusFirstCell()" [attr.aria-activedescendant]="activeDescendant"
66
(keydown)="navigation.headerNavigation($event)" role="rowgroup" [style.width.px]='calcWidth' #theadRow>
77
<div class="igx-grid__tr" role="row" [style.width.px]='calcWidth'>
88
<span *ngIf="hasMovableColumns && draggedColumn && pinnedColumns.length <= 0"

projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<ng-content select="igx-grid-toolbar"></ng-content>
22

33
<div class="igx-grid__thead">
4-
<div class="igx-grid__thead-wrapper" role="rowgroup" [style.width.px]='calcWidth' tabindex="0" [attr.aria-activedescendant]="activeDescendant" (focus)="navigation.focusFirstCell()" (keydown)="navigation.headerNavigation($event)" #theadRow>
4+
<div class="igx-grid__thead-wrapper" (keydown.meta.c)="copyHandler($event)" (keydown.control.c)="copyHandler($event)" (copy)="copyHandler($event)" role="rowgroup" [style.width.px]='calcWidth' tabindex="0" [attr.aria-activedescendant]="activeDescendant" (focus)="navigation.focusFirstCell()" (keydown)="navigation.headerNavigation($event)" #theadRow>
55
<div class="igx-grid__tr" [style.width.px]='calcWidth' role="row">
66
<span *ngIf="hasMovableColumns && draggedColumn && pinnedColumns.length <= 0"
77
[igxColumnMovingDrop]="headerContainer" [attr.droppable]="true" id="left"

projects/igniteui-angular/src/lib/services/csv/char-separated-value-data.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,16 @@ export class CharSeparatedValueData {
1717
this.setDelimiter(valueDelimiter);
1818
}
1919

20-
public prepareData() {
20+
public prepareData(key?: any[]) {
2121
if (!this._data || this._data.length === 0) {
2222
return '';
2323
}
24-
25-
const keys = ExportUtilities.getKeysFromData(this._data);
24+
let keys = [];
25+
if (key){
26+
keys = key;
27+
}else {
28+
keys = ExportUtilities.getKeysFromData(this._data);
29+
}
2630

2731
if (keys.length === 0) {
2832
return '';

0 commit comments

Comments
 (0)