Skip to content

Commit

Permalink
Merge branch 'tzhelev/samples-routing' of https://github.com/IgniteUI…
Browse files Browse the repository at this point in the history
…/igniteui-angular-samples into tzhelev/samples-routing
  • Loading branch information
Tacho committed Jul 19, 2018
2 parents 8d97fef + d7c17eb commit bba2bab
Show file tree
Hide file tree
Showing 15 changed files with 400 additions and 61 deletions.
5 changes: 5 additions & 0 deletions src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ import { FilteringSampleComponent } from "./grid/grid-filtering-sample/grid-filt
import { GridGroupBySampleComponent } from "./grid/grid-groupby-sample/grid-groupby-sample.component";
import { GridMovingSampleComponent } from "./grid/grid-moving-sample/grid-moving-sample.component";
import { PagingSampleComponent } from "./grid/grid-paging-sample/grid-paging-sample.component";
import { GridPasteSampleComponent } from "./grid/grid-paste/grid-paste-sample.component";
import { RemoteFilteringSampleComponent } from "./grid/grid-remote-filtering-sample/remote-filtering-sample.component";
import { ResizingSampleComponent } from "./grid/grid-resizing-sample/grid-resizing-sample.component";
import { FinancialSampleComponent } from "./grid/grid-sample-2/grid-sample-2.component";
Expand Down Expand Up @@ -1206,6 +1207,10 @@ export const appRoutes: Routes = [
component: GridMultiColumnHeadersComponent,
data: { displayName: "Grid Multi Column Headers", parentName: "Grid" },
path: "multi-column-headers"
},
{
component: GridPasteSampleComponent,
path: "grid-paste"
}
];

Expand Down
4 changes: 4 additions & 0 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ import { FilteringSampleComponent } from "./grid/grid-filtering-sample/grid-filt
import { GridGroupBySampleComponent } from "./grid/grid-groupby-sample/grid-groupby-sample.component";
import { GridMovingSampleComponent } from "./grid/grid-moving-sample/grid-moving-sample.component";
import { PagingSampleComponent } from "./grid/grid-paging-sample/grid-paging-sample.component";
import { GridPasteSampleComponent } from "./grid/grid-paste/grid-paste-sample.component";
import { PasteHandler } from "./grid/grid-paste/paste-handler.directive";
import { RemoteFilteringSampleComponent } from "./grid/grid-remote-filtering-sample/remote-filtering-sample.component";
import { ResizingSampleComponent } from "./grid/grid-resizing-sample/grid-resizing-sample.component";
import { FinancialSampleComponent } from "./grid/grid-sample-2/grid-sample-2.component";
Expand Down Expand Up @@ -379,6 +381,8 @@ import { ToggleComponent } from "./toggle/toggle.component";
RadioGroupSampleComponent,
GridMovingSampleComponent,
GridMultiColumnHeadersComponent,
GridPasteSampleComponent,
PasteHandler,
RemoteFilteringSampleComponent,
ReactiveFormsSampleComponent,
RadioGroupSampleComponent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
border-radius: 10px;
box-shadow: 1px 1px 2px 2px rgba(50, 50, 50, 0.25);
igx-column-hiding {
height: 100%;
height: 460px;
}
}

Expand Down
64 changes: 64 additions & 0 deletions src/app/grid/grid-paste/data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
export const LOCAL_DATA = [{
Country: "USA",
ID: 1,
Name: "Davolio, Nancy",
Phone: "(206) 555-9857",
Title: "Sales Representative"
},
{
Country: "USA",
ID: 2,
Name: "Fuller, Andrew",
Phone: "(206) 555-9482",
Title: "Vice President, Sales"
},
{
Country: "USA",
ID: 3,
Name: "Leverling, Janet",
Phone: "(206) 555-3412",
Title: "Sales Representative"
},
{
Country: "USA",
ID: 4,
Name: "Peacock, Margaret",
Phone: "(206) 555-8122",
Title: "Sales Representative"
},
{
Country: "UK",
ID: 5,
Name: "Buchanan, Steven",
Phone: "(71) 555-4848",
Title: "Sales Manager"
},
{
Country: "UK",
ID: 6,
Name: "Suyama, Michael",
Phone: "(71) 555-7773",
Title: "Sales Representative"
},
{
Country: "UK",
ID: 7,
Name: "King, Robert",
Phone: "(71) 555-5598",
Title: "Sales Representative"
},
{
Country: "USA",
ID: 8,
Name: "Callahan, Laura",
Phone: "(206) 555-1189",
Title: "Inside Sales Coordinator"
},
{
Country: "UK",
ID: 9,
Name: "Dodsworth, Anne",
Phone: "(71) 555-4444",
Title: "Sales Representative"
}
];
15 changes: 15 additions & 0 deletions src/app/grid/grid-paste/grid-paste-sample.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<div class="grid__wrapper">
<button igxButton="raised" (click)="toggleDropDown($event)">Paste Options</button>
<igx-drop-down (onSelection)="selectionChange($event)">
<igx-drop-down-item *ngFor="let item of comboData">
{{ item }}
</igx-drop-down-item>
</igx-drop-down>
<igx-grid #grid1 [data]="data" [width]="'100%'" [height]="'505px'" [autoGenerate]="false" paste-handler (onDataProcessed)="dataPasted($event)" [primaryKey]="'ID'">
<igx-column [field]="'ID'" [hidden]="true"></igx-column>
<igx-column [field]="'Name'"></igx-column>
<igx-column [field]="'Title'"></igx-column>
<igx-column [field]="'Phone'"></igx-column>
<igx-column [field]="'Country'"></igx-column>
</igx-grid>
</div>
36 changes: 36 additions & 0 deletions src/app/grid/grid-paste/grid-paste-sample.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
.grid-controls {
display: flex;
flex-flow: column nowrap;
justify-content: space-between;
margin: 0 16px 24px;

igx-switch {
margin-top: 24px;
}

}

.grid__wrapper {
margin: 0 16px;
}

.header-icon {
font-size: 1.4em;
width: 1.1em;
height: 1.1em;
float: right;
cursor: pointer;
}

.header {
height: 100%;
}

.igx-grid__th .title {
width: 100%;
cursor: auto;
}

.igx-grid__td-text {
padding-right: 3px;
}
152 changes: 152 additions & 0 deletions src/app/grid/grid-paste/grid-paste-sample.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import { Component, Directive, HostListener, ViewChild, ViewEncapsulation} from "@angular/core";
import {
CloseScrollStrategy,
ConnectedPositioningStrategy,
HorizontalAlignment,
IgxDropDownComponent,
IgxGridComponent,
VerticalAlignment
} from "igniteui-angular";

import { PasteHandler} from "./paste-handler.directive";

import { LOCAL_DATA } from "./data";

import { take } from "rxjs/operators";

@Component({
encapsulation: ViewEncapsulation.None,
selector: "app-grid-paste-sample",
styleUrls: ["./grid-paste-sample.component.scss"],
templateUrl: "./grid-paste-sample.component.html"
})
export class GridPasteSampleComponent {
@ViewChild("grid1", { read: IgxGridComponent }) public grid1: IgxGridComponent;
@ViewChild(IgxDropDownComponent) public igxDropDown: IgxDropDownComponent;
public data;
public comboData = [
"Paste data as new records",
"Paste starting from active cell"
];
public pasteMode = this.comboData[0];
private _positionSettings = {
horizontalStartPoint: HorizontalAlignment.Left,
verticalStartPoint: VerticalAlignment.Bottom
};
private _overlaySettings = {
closeOnOutsideClick: true,
modal: false,
positionStrategy: new ConnectedPositioningStrategy(this._positionSettings),
scrollStrategy: new CloseScrollStrategy()
};

constructor() {
this.data = LOCAL_DATA;
}

public ngOnInit() {
this.grid1.verticalScrollContainer.onChunkLoad.pipe().subscribe(() => {
if (this.grid1.rowList) {
this.clearStyles();
}
});
}

public toggleDropDown(eventArgs) {
this._overlaySettings.positionStrategy.settings.target = eventArgs.target;
this.igxDropDown.toggle(this._overlaySettings);
}

public selectionChange(eventArgs) {
this.pasteMode = eventArgs.newSelection.elementRef.nativeElement.textContent.trim();
}

public dataPasted(processedData) {
if (this.pasteMode === "Paste data as new records") {
this.addRecords(processedData);
} else {
this.updateRecords(processedData);
}
}

public addRecords(processedData: any[]) {
const columns = this.grid1.visibleColumns;
const pk = this.grid1.primaryKey;
const addedData = [];
for (const curentDataRow of processedData) {
const rowData = {};
for (const col of columns) {
rowData[col.field] = curentDataRow[col.visibleIndex];
}
// generate PK
rowData[pk] = this.grid1.data.length + 1;
this.grid1.addRow(rowData);
addedData.push(rowData);
this.grid1.cdr.detectChanges();
}
// scroll to last added row
this.grid1.verticalScrollContainer.scrollTo(this.grid1.data.length);

this.grid1.verticalScrollContainer.onChunkLoad.pipe(take(1)).subscribe(() => {
this.clearStyles();
for (const data of addedData) {
const row = this.grid1.getRowByKey(data[pk]);
if (row) {
row.nativeElement.style["font-style"] = "italic";
row.nativeElement.style.color = "gray";
}
}
});
}
public updateRecords(processedData: any[]) {
const cell = this.grid1.selectedCells[0];
const pk = this.grid1.primaryKey;
if (!cell) { return; }
const rowIndex = cell.row.index;
// const rowPkValue = cell.row.rowData[pk];
const cellIndex = cell.column.visibleIndex;
const columns = this.grid1.visibleColumns;
let index = 0;
const updatedRecsPK = [];
for (const curentDataRow of processedData) {
const rowData = {};
const dataRec = this.grid1.data[rowIndex + index];
const rowPkValue = dataRec ? dataRec[pk] : this.grid1.data.length + 1;
rowData[pk] = rowPkValue;
for (let j = 0; j < columns.length; j++) {
let currentCell;
if (j >= cellIndex) {
currentCell = curentDataRow.shift();
}
const colKey = columns[j].field;
rowData[colKey] = currentCell || (!!dataRec ? dataRec[colKey] : null);
}
if (!dataRec) {
// no rec to update, add instead
rowData[pk] = rowPkValue;
this.grid1.addRow(rowData);
continue;
}
this.grid1.updateRow(rowData, rowPkValue);
this.grid1.cdr.detectChanges();
updatedRecsPK.push(rowPkValue);
index++;
}

this.clearStyles();
for (const pkVal of updatedRecsPK) {
const row = this.grid1.getRowByKey(pkVal);
if (row) {
row.nativeElement.style["font-style"] = "italic";
row.nativeElement.style.color = "gray";
}
}
}

protected clearStyles() {
for (const row of this.grid1.rowList.toArray()) {
row.nativeElement.style["font-style"] = "";
row.nativeElement.style.color = "";
}
}
}
75 changes: 75 additions & 0 deletions src/app/grid/grid-paste/paste-handler.directive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { Directive, EventEmitter, HostListener, Output} from "@angular/core";

@Directive({ selector: "[paste-handler]" })
export class PasteHandler {
public textArea;

@Output()
public onDataProcessed = new EventEmitter<any>();

public ngOnInit(): void {
const div = document.createElement("div");
const divStyle = div.style;
divStyle.position = "fixed";
divStyle.top = "-10000px";
divStyle.left = "-10000px";
document.body.appendChild(div);
this.textArea = document.createElement("textarea");
const style = this.textArea.style;
style.opacity = "0";
style.overflow = "hidden";
div.appendChild(this.textArea);

this.textArea.addEventListener("paste", (eventArgs) => { this.onPaste(eventArgs); });
}

@HostListener("focusin", ["$event"])
public focusIn(eventArgs) {
}

@HostListener("keydown", ["$event"])
public ControlV(eventArgs) {
const ctrl = eventArgs.ctrlKey;
const key = eventArgs.keyCode;
// Ctrl-V || Shift-Ins || Cmd-V
if ((ctrl || eventArgs.metaKey) && key === 86 || eventArgs.shiftKey && key === 45) {
this.textArea.focus();
}
}

public onPaste(eventArgs) {
let data;
const clData = "clipboardData";

// get clipboard data - from window.cliboardData for IE or from the original event's argumets.
if (window[clData]) {
window.event.returnValue = false;
data = window[clData].getData("text");
} else {
data = eventArgs[clData].getData("text/plain");
}

// process the clipboard data
const processedData = this.processData(data);

this.onDataProcessed.emit(processedData);
}

public processData(data) {
const pasteData = data.split("\n");
for (let i = 0; i < pasteData.length; i++) {
pasteData[i] = pasteData[i].split("\t");
// Check if last row is a dummy row
if (pasteData[pasteData.length - 1].length === 1 && pasteData[pasteData.length - 1][0] === "") {
pasteData.pop();
}
// remove empty data
if (pasteData.length === 1 &&
pasteData[0].length === 1 &&
(pasteData[0][0] === "" || pasteData[0][0] === "\r")) {
pasteData.pop();
}
}
return pasteData;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="sample-wrapper dark-grid">
<div class="grid__wrapper">
<igx-grid #grid [data]="remoteData | async" [height]="'500px'" [width]="'100%'" [autoGenerate]='false' (onDataPreLoad)="processData()"
(onSortingDone)="processData()" (onFilteringDone)="processData()">
<igx-column [field]="'ID'" [sortable]="true"></igx-column>
Expand Down
Loading

0 comments on commit bba2bab

Please sign in to comment.