Skip to content

Commit bba2bab

Browse files
author
Tacho
committed
Merge branch 'tzhelev/samples-routing' of https://github.com/IgniteUI/igniteui-angular-samples into tzhelev/samples-routing
2 parents 8d97fef + d7c17eb commit bba2bab

15 files changed

+400
-61
lines changed

src/app/app-routing.module.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ import { FilteringSampleComponent } from "./grid/grid-filtering-sample/grid-filt
149149
import { GridGroupBySampleComponent } from "./grid/grid-groupby-sample/grid-groupby-sample.component";
150150
import { GridMovingSampleComponent } from "./grid/grid-moving-sample/grid-moving-sample.component";
151151
import { PagingSampleComponent } from "./grid/grid-paging-sample/grid-paging-sample.component";
152+
import { GridPasteSampleComponent } from "./grid/grid-paste/grid-paste-sample.component";
152153
import { RemoteFilteringSampleComponent } from "./grid/grid-remote-filtering-sample/remote-filtering-sample.component";
153154
import { ResizingSampleComponent } from "./grid/grid-resizing-sample/grid-resizing-sample.component";
154155
import { FinancialSampleComponent } from "./grid/grid-sample-2/grid-sample-2.component";
@@ -1206,6 +1207,10 @@ export const appRoutes: Routes = [
12061207
component: GridMultiColumnHeadersComponent,
12071208
data: { displayName: "Grid Multi Column Headers", parentName: "Grid" },
12081209
path: "multi-column-headers"
1210+
},
1211+
{
1212+
component: GridPasteSampleComponent,
1213+
path: "grid-paste"
12091214
}
12101215
];
12111216

src/app/app.module.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ import { FilteringSampleComponent } from "./grid/grid-filtering-sample/grid-filt
124124
import { GridGroupBySampleComponent } from "./grid/grid-groupby-sample/grid-groupby-sample.component";
125125
import { GridMovingSampleComponent } from "./grid/grid-moving-sample/grid-moving-sample.component";
126126
import { PagingSampleComponent } from "./grid/grid-paging-sample/grid-paging-sample.component";
127+
import { GridPasteSampleComponent } from "./grid/grid-paste/grid-paste-sample.component";
128+
import { PasteHandler } from "./grid/grid-paste/paste-handler.directive";
127129
import { RemoteFilteringSampleComponent } from "./grid/grid-remote-filtering-sample/remote-filtering-sample.component";
128130
import { ResizingSampleComponent } from "./grid/grid-resizing-sample/grid-resizing-sample.component";
129131
import { FinancialSampleComponent } from "./grid/grid-sample-2/grid-sample-2.component";
@@ -379,6 +381,8 @@ import { ToggleComponent } from "./toggle/toggle.component";
379381
RadioGroupSampleComponent,
380382
GridMovingSampleComponent,
381383
GridMultiColumnHeadersComponent,
384+
GridPasteSampleComponent,
385+
PasteHandler,
382386
RemoteFilteringSampleComponent,
383387
ReactiveFormsSampleComponent,
384388
RadioGroupSampleComponent,

src/app/grid/grid-column-hiding-sample/grid-column-hiding-sample.component.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
border-radius: 10px;
1616
box-shadow: 1px 1px 2px 2px rgba(50, 50, 50, 0.25);
1717
igx-column-hiding {
18-
height: 100%;
18+
height: 460px;
1919
}
2020
}
2121

src/app/grid/grid-paste/data.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
export const LOCAL_DATA = [{
2+
Country: "USA",
3+
ID: 1,
4+
Name: "Davolio, Nancy",
5+
Phone: "(206) 555-9857",
6+
Title: "Sales Representative"
7+
},
8+
{
9+
Country: "USA",
10+
ID: 2,
11+
Name: "Fuller, Andrew",
12+
Phone: "(206) 555-9482",
13+
Title: "Vice President, Sales"
14+
},
15+
{
16+
Country: "USA",
17+
ID: 3,
18+
Name: "Leverling, Janet",
19+
Phone: "(206) 555-3412",
20+
Title: "Sales Representative"
21+
},
22+
{
23+
Country: "USA",
24+
ID: 4,
25+
Name: "Peacock, Margaret",
26+
Phone: "(206) 555-8122",
27+
Title: "Sales Representative"
28+
},
29+
{
30+
Country: "UK",
31+
ID: 5,
32+
Name: "Buchanan, Steven",
33+
Phone: "(71) 555-4848",
34+
Title: "Sales Manager"
35+
},
36+
{
37+
Country: "UK",
38+
ID: 6,
39+
Name: "Suyama, Michael",
40+
Phone: "(71) 555-7773",
41+
Title: "Sales Representative"
42+
},
43+
{
44+
Country: "UK",
45+
ID: 7,
46+
Name: "King, Robert",
47+
Phone: "(71) 555-5598",
48+
Title: "Sales Representative"
49+
},
50+
{
51+
Country: "USA",
52+
ID: 8,
53+
Name: "Callahan, Laura",
54+
Phone: "(206) 555-1189",
55+
Title: "Inside Sales Coordinator"
56+
},
57+
{
58+
Country: "UK",
59+
ID: 9,
60+
Name: "Dodsworth, Anne",
61+
Phone: "(71) 555-4444",
62+
Title: "Sales Representative"
63+
}
64+
];
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<div class="grid__wrapper">
2+
<button igxButton="raised" (click)="toggleDropDown($event)">Paste Options</button>
3+
<igx-drop-down (onSelection)="selectionChange($event)">
4+
<igx-drop-down-item *ngFor="let item of comboData">
5+
{{ item }}
6+
</igx-drop-down-item>
7+
</igx-drop-down>
8+
<igx-grid #grid1 [data]="data" [width]="'100%'" [height]="'505px'" [autoGenerate]="false" paste-handler (onDataProcessed)="dataPasted($event)" [primaryKey]="'ID'">
9+
<igx-column [field]="'ID'" [hidden]="true"></igx-column>
10+
<igx-column [field]="'Name'"></igx-column>
11+
<igx-column [field]="'Title'"></igx-column>
12+
<igx-column [field]="'Phone'"></igx-column>
13+
<igx-column [field]="'Country'"></igx-column>
14+
</igx-grid>
15+
</div>
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
.grid-controls {
2+
display: flex;
3+
flex-flow: column nowrap;
4+
justify-content: space-between;
5+
margin: 0 16px 24px;
6+
7+
igx-switch {
8+
margin-top: 24px;
9+
}
10+
11+
}
12+
13+
.grid__wrapper {
14+
margin: 0 16px;
15+
}
16+
17+
.header-icon {
18+
font-size: 1.4em;
19+
width: 1.1em;
20+
height: 1.1em;
21+
float: right;
22+
cursor: pointer;
23+
}
24+
25+
.header {
26+
height: 100%;
27+
}
28+
29+
.igx-grid__th .title {
30+
width: 100%;
31+
cursor: auto;
32+
}
33+
34+
.igx-grid__td-text {
35+
padding-right: 3px;
36+
}
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
import { Component, Directive, HostListener, ViewChild, ViewEncapsulation} from "@angular/core";
2+
import {
3+
CloseScrollStrategy,
4+
ConnectedPositioningStrategy,
5+
HorizontalAlignment,
6+
IgxDropDownComponent,
7+
IgxGridComponent,
8+
VerticalAlignment
9+
} from "igniteui-angular";
10+
11+
import { PasteHandler} from "./paste-handler.directive";
12+
13+
import { LOCAL_DATA } from "./data";
14+
15+
import { take } from "rxjs/operators";
16+
17+
@Component({
18+
encapsulation: ViewEncapsulation.None,
19+
selector: "app-grid-paste-sample",
20+
styleUrls: ["./grid-paste-sample.component.scss"],
21+
templateUrl: "./grid-paste-sample.component.html"
22+
})
23+
export class GridPasteSampleComponent {
24+
@ViewChild("grid1", { read: IgxGridComponent }) public grid1: IgxGridComponent;
25+
@ViewChild(IgxDropDownComponent) public igxDropDown: IgxDropDownComponent;
26+
public data;
27+
public comboData = [
28+
"Paste data as new records",
29+
"Paste starting from active cell"
30+
];
31+
public pasteMode = this.comboData[0];
32+
private _positionSettings = {
33+
horizontalStartPoint: HorizontalAlignment.Left,
34+
verticalStartPoint: VerticalAlignment.Bottom
35+
};
36+
private _overlaySettings = {
37+
closeOnOutsideClick: true,
38+
modal: false,
39+
positionStrategy: new ConnectedPositioningStrategy(this._positionSettings),
40+
scrollStrategy: new CloseScrollStrategy()
41+
};
42+
43+
constructor() {
44+
this.data = LOCAL_DATA;
45+
}
46+
47+
public ngOnInit() {
48+
this.grid1.verticalScrollContainer.onChunkLoad.pipe().subscribe(() => {
49+
if (this.grid1.rowList) {
50+
this.clearStyles();
51+
}
52+
});
53+
}
54+
55+
public toggleDropDown(eventArgs) {
56+
this._overlaySettings.positionStrategy.settings.target = eventArgs.target;
57+
this.igxDropDown.toggle(this._overlaySettings);
58+
}
59+
60+
public selectionChange(eventArgs) {
61+
this.pasteMode = eventArgs.newSelection.elementRef.nativeElement.textContent.trim();
62+
}
63+
64+
public dataPasted(processedData) {
65+
if (this.pasteMode === "Paste data as new records") {
66+
this.addRecords(processedData);
67+
} else {
68+
this.updateRecords(processedData);
69+
}
70+
}
71+
72+
public addRecords(processedData: any[]) {
73+
const columns = this.grid1.visibleColumns;
74+
const pk = this.grid1.primaryKey;
75+
const addedData = [];
76+
for (const curentDataRow of processedData) {
77+
const rowData = {};
78+
for (const col of columns) {
79+
rowData[col.field] = curentDataRow[col.visibleIndex];
80+
}
81+
// generate PK
82+
rowData[pk] = this.grid1.data.length + 1;
83+
this.grid1.addRow(rowData);
84+
addedData.push(rowData);
85+
this.grid1.cdr.detectChanges();
86+
}
87+
// scroll to last added row
88+
this.grid1.verticalScrollContainer.scrollTo(this.grid1.data.length);
89+
90+
this.grid1.verticalScrollContainer.onChunkLoad.pipe(take(1)).subscribe(() => {
91+
this.clearStyles();
92+
for (const data of addedData) {
93+
const row = this.grid1.getRowByKey(data[pk]);
94+
if (row) {
95+
row.nativeElement.style["font-style"] = "italic";
96+
row.nativeElement.style.color = "gray";
97+
}
98+
}
99+
});
100+
}
101+
public updateRecords(processedData: any[]) {
102+
const cell = this.grid1.selectedCells[0];
103+
const pk = this.grid1.primaryKey;
104+
if (!cell) { return; }
105+
const rowIndex = cell.row.index;
106+
// const rowPkValue = cell.row.rowData[pk];
107+
const cellIndex = cell.column.visibleIndex;
108+
const columns = this.grid1.visibleColumns;
109+
let index = 0;
110+
const updatedRecsPK = [];
111+
for (const curentDataRow of processedData) {
112+
const rowData = {};
113+
const dataRec = this.grid1.data[rowIndex + index];
114+
const rowPkValue = dataRec ? dataRec[pk] : this.grid1.data.length + 1;
115+
rowData[pk] = rowPkValue;
116+
for (let j = 0; j < columns.length; j++) {
117+
let currentCell;
118+
if (j >= cellIndex) {
119+
currentCell = curentDataRow.shift();
120+
}
121+
const colKey = columns[j].field;
122+
rowData[colKey] = currentCell || (!!dataRec ? dataRec[colKey] : null);
123+
}
124+
if (!dataRec) {
125+
// no rec to update, add instead
126+
rowData[pk] = rowPkValue;
127+
this.grid1.addRow(rowData);
128+
continue;
129+
}
130+
this.grid1.updateRow(rowData, rowPkValue);
131+
this.grid1.cdr.detectChanges();
132+
updatedRecsPK.push(rowPkValue);
133+
index++;
134+
}
135+
136+
this.clearStyles();
137+
for (const pkVal of updatedRecsPK) {
138+
const row = this.grid1.getRowByKey(pkVal);
139+
if (row) {
140+
row.nativeElement.style["font-style"] = "italic";
141+
row.nativeElement.style.color = "gray";
142+
}
143+
}
144+
}
145+
146+
protected clearStyles() {
147+
for (const row of this.grid1.rowList.toArray()) {
148+
row.nativeElement.style["font-style"] = "";
149+
row.nativeElement.style.color = "";
150+
}
151+
}
152+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { Directive, EventEmitter, HostListener, Output} from "@angular/core";
2+
3+
@Directive({ selector: "[paste-handler]" })
4+
export class PasteHandler {
5+
public textArea;
6+
7+
@Output()
8+
public onDataProcessed = new EventEmitter<any>();
9+
10+
public ngOnInit(): void {
11+
const div = document.createElement("div");
12+
const divStyle = div.style;
13+
divStyle.position = "fixed";
14+
divStyle.top = "-10000px";
15+
divStyle.left = "-10000px";
16+
document.body.appendChild(div);
17+
this.textArea = document.createElement("textarea");
18+
const style = this.textArea.style;
19+
style.opacity = "0";
20+
style.overflow = "hidden";
21+
div.appendChild(this.textArea);
22+
23+
this.textArea.addEventListener("paste", (eventArgs) => { this.onPaste(eventArgs); });
24+
}
25+
26+
@HostListener("focusin", ["$event"])
27+
public focusIn(eventArgs) {
28+
}
29+
30+
@HostListener("keydown", ["$event"])
31+
public ControlV(eventArgs) {
32+
const ctrl = eventArgs.ctrlKey;
33+
const key = eventArgs.keyCode;
34+
// Ctrl-V || Shift-Ins || Cmd-V
35+
if ((ctrl || eventArgs.metaKey) && key === 86 || eventArgs.shiftKey && key === 45) {
36+
this.textArea.focus();
37+
}
38+
}
39+
40+
public onPaste(eventArgs) {
41+
let data;
42+
const clData = "clipboardData";
43+
44+
// get clipboard data - from window.cliboardData for IE or from the original event's argumets.
45+
if (window[clData]) {
46+
window.event.returnValue = false;
47+
data = window[clData].getData("text");
48+
} else {
49+
data = eventArgs[clData].getData("text/plain");
50+
}
51+
52+
// process the clipboard data
53+
const processedData = this.processData(data);
54+
55+
this.onDataProcessed.emit(processedData);
56+
}
57+
58+
public processData(data) {
59+
const pasteData = data.split("\n");
60+
for (let i = 0; i < pasteData.length; i++) {
61+
pasteData[i] = pasteData[i].split("\t");
62+
// Check if last row is a dummy row
63+
if (pasteData[pasteData.length - 1].length === 1 && pasteData[pasteData.length - 1][0] === "") {
64+
pasteData.pop();
65+
}
66+
// remove empty data
67+
if (pasteData.length === 1 &&
68+
pasteData[0].length === 1 &&
69+
(pasteData[0][0] === "" || pasteData[0][0] === "\r")) {
70+
pasteData.pop();
71+
}
72+
}
73+
return pasteData;
74+
}
75+
}

src/app/grid/grid-remote-filtering-sample/remote-filtering-sample.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<div class="sample-wrapper dark-grid">
1+
<div class="grid__wrapper">
22
<igx-grid #grid [data]="remoteData | async" [height]="'500px'" [width]="'100%'" [autoGenerate]='false' (onDataPreLoad)="processData()"
33
(onSortingDone)="processData()" (onFilteringDone)="processData()">
44
<igx-column [field]="'ID'" [sortable]="true"></igx-column>

0 commit comments

Comments
 (0)