Skip to content

Commit 06f6c11

Browse files
committed
feat(tree-grid): adding tree cells #2530
1 parent cdea6f6 commit 06f6c11

10 files changed

+580
-311
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<ng-template #defaultCell igxTextHighlight [cssClass]="highlightClass" [activeCssClass]="activeHighlightClass" [groupName]="gridID"
2+
[value]="formatter ? formatter(value) : value" [row]="row.rowData" [column]="column.field" [containerClass]="'igx-grid__td-text'">
3+
<ng-container *ngIf="column.dataType === 'boolean' || column.dataType === 'string' || formatter; else default" >
4+
<div class="igx-grid__td-text">{{ formatter ? formatter(value) : value }}</div>
5+
</ng-container>
6+
<ng-template #default>
7+
<div class="igx-grid__td-text">{{ column.dataType === 'number' ? (value | igxdecimal) : (value | igxdate) }}</div>
8+
</ng-template>
9+
</ng-template>
10+
<ng-template #inlineEditor let-cell="cell">
11+
<ng-container *ngIf="column.dataType === 'string'">
12+
<igx-input-group>
13+
<input igxInput [(ngModel)]="gridAPI.get_cell_inEditMode(gridID).cell.editValue" [igxFocus]="focused">
14+
</igx-input-group>
15+
</ng-container>
16+
<ng-container *ngIf="column.dataType === 'number'">
17+
<igx-input-group>
18+
<input igxInput [(ngModel)]="gridAPI.get_cell_inEditMode(gridID).cell.editValue" [igxFocus]="focused" type="number">
19+
</igx-input-group>
20+
</ng-container>
21+
<ng-container *ngIf="column.dataType === 'boolean'">
22+
<igx-checkbox [(ngModel)]="gridAPI.get_cell_inEditMode(gridID).cell.editValue" [checked]="gridAPI.get_cell_inEditMode(gridID).cell.editValue" [disableRipple]="true"></igx-checkbox>
23+
</ng-container>
24+
<ng-container *ngIf="column.dataType === 'date'">
25+
<igx-datePicker [outlet]="grid.outletDirective" [(ngModel)]="gridAPI.get_cell_inEditMode(gridID).cell.editValue" [labelVisibility]="false"></igx-datePicker>
26+
</ng-container>
27+
</ng-template>
28+
<ng-container *ngIf="indentation > 0">
29+
<div class="igx-grid__group-row--padding-level-{{indentation}}"></div>
30+
</ng-container>
31+
<div [style.visibility]="hasChildren ? 'visible' : 'hidden'" (click)="toggle()">
32+
<igx-icon *ngIf="!expanded" fontSet="material" name="chevron_right"></igx-icon>
33+
<igx-icon *ngIf="expanded" fontSet="material" name="expand_more"></igx-icon>
34+
</div>
35+
<ng-container *ngTemplateOutlet="template; context: context">
36+
</ng-container>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { Component, forwardRef, Input, HostBinding } from '@angular/core';
2+
import { IgxTreeGridComponent } from './tree-grid.component';
3+
import { IgxRowComponent } from '../grid-common/row.component';
4+
import { IFlattenedRecord } from './tree-grid.pipes';
5+
import { IgxGridCellComponent } from '../grid-common/cell.component';
6+
import { IgxTreeGridRowComponent } from './tree-grid-row.component';
7+
8+
@Component({
9+
selector: 'igx-tree-grid-cell',
10+
templateUrl: 'tree-cell.component.html'
11+
})
12+
export class IgxTreeGridCellComponent extends IgxGridCellComponent {
13+
public get indentation() {
14+
const flatRowComponent = <IgxTreeGridRowComponent>this.row;
15+
return flatRowComponent.flatRow.indentationLevel;
16+
}
17+
18+
public get hasChildren() {
19+
const flatRowComponent = <IgxTreeGridRowComponent>this.row;
20+
return flatRowComponent.flatRow.hasChildren;
21+
}
22+
23+
@HostBinding('attr.aria-expanded')
24+
get expanded(): boolean {
25+
return true;
26+
}
27+
28+
public toggle() {
29+
}
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<ng-container *ngIf="indentation > 0">
2+
<div class="igx-grid__row-indentation igx-grid__row-indentation--level-{{indentation}}"></div>
3+
</ng-container>
4+
<ng-container *ngIf="rowSelectable">
5+
<div class="igx-grid__cbx-selection">
6+
<igx-checkbox [checked]="isSelected" (change)="onCheckboxClick($event)" disableRipple="true" [aria-label]="rowCheckboxAriaLabel"></igx-checkbox>
7+
</div>
8+
</ng-container>
9+
<ng-container *ngIf="pinnedColumns.length > 0">
10+
<igx-grid-cell *ngFor="let col of notGroups(pinnedColumns)" [column]="col" [row]="this" [style.min-width.px]="col.width" [style.flex-basis.px]="col.width" [value]="rowData[col.field]" [cellTemplate]="col.bodyTemplate"></igx-grid-cell>
11+
</ng-container>
12+
<ng-template igxFor let-col [igxForOf]="notGroups(unpinnedColumns)" [igxForScrollContainer]="grid.parentVirtDir" let-colIndex="index" [igxForScrollOrientation]="'horizontal'" [igxForContainerSize]='grid.unpinnedWidth' [igxForTrackBy]='grid.trackColumnChanges' #igxDirRef>
13+
<ng-template #cellTemplate>
14+
<igx-grid-cell [column]="col" [row]="this" [style.min-width.px]="col.width" [style.flex-basis.px]="col.width" [value]="rowData[col.field]" [cellTemplate]="col.bodyTemplate" #treeCell></igx-grid-cell>
15+
</ng-template>
16+
<ng-template #treeCellTemplate>
17+
<igx-tree-grid-cell [column]="col" [row]="this" [style.min-width.px]="col.width" [style.flex-basis.px]="col.width" [value]="rowData[col.field]" [cellTemplate]="col.bodyTemplate" #treeCell></igx-tree-grid-cell>
18+
</ng-template>
19+
<ng-container *ngTemplateOutlet="colIndex === 0 ? treeCellTemplate : cellTemplate; context: getContext(col)"></ng-container>
20+
</ng-template>
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,57 @@
1-
import { Component, forwardRef } from '@angular/core';
1+
import { Component, forwardRef, Input, ViewChildren, QueryList, ViewChild } from '@angular/core';
22
import { IgxTreeGridComponent } from './tree-grid.component';
33
import { IgxRowComponent } from '../grid-common/row.component';
4+
import { IFlattenedRecord } from './tree-grid.pipes';
5+
import { IgxTreeGridCellComponent } from './tree-cell.component';
6+
import { IgxGridCellComponent } from '../grid-common';
47

58
@Component({
69
selector: 'igx-tree-grid-row',
7-
templateUrl: '../grid-common/row.component.html',
10+
templateUrl: 'tree-grid-row.component.html',
811
providers: [{provide: IgxRowComponent, useExisting: forwardRef(() => IgxTreeGridRowComponent)}]
912
})
1013
export class IgxTreeGridRowComponent extends IgxRowComponent<IgxTreeGridComponent> {
14+
private _flatRow: IFlattenedRecord;
15+
16+
/**
17+
* The rendered cells in the row component.
18+
*
19+
* ```typescript
20+
* // get the cells of the third selected row
21+
* let selectedRowCells = this.grid.selectedRows[2].cells;
22+
* ```
23+
*/
24+
@ViewChildren('treeCell')
25+
public cells: QueryList<any>;
26+
27+
/**
28+
* The flat data tow passed to the tree grid row component.
29+
*
30+
* ```typescript
31+
* ```
32+
*/
33+
@Input()
34+
public get flatRow(): IFlattenedRecord {
35+
return this._flatRow;
36+
}
37+
public set flatRow(value: IFlattenedRecord) {
38+
if (this._flatRow !== value) {
39+
this._flatRow = value;
40+
this.rowData = this._flatRow.data;
41+
}
42+
}
43+
44+
/**
45+
* @hidden
46+
*/
47+
public getContext(col): any {
48+
return {
49+
$implicit: col,
50+
templateID: col.index === 0 ? 'treeCell' : 'cell'
51+
};
52+
}
53+
54+
// public get indentation() {
55+
// return this._flatRow.indentationLevel;
56+
// }
1157
}

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@
4343
<div class="igx-grid__tbody" role="rowgroup" [style.height.px]='calcHeight' [style.width.px]='calcWidth' #tbody (scroll)='scrollHandler($event)'>
4444
<span *ngIf="hasMovableColumns && draggedColumn && pinnedColumns.length <= 0" [igxColumnMovingDrop]="parentVirtDir" [attr.droppable]="true" id="left" class="igx-grid__scroll-on-drag-left"></span>
4545
<span *ngIf="hasMovableColumns && draggedColumn && pinnedColumns.length > 0" [igxColumnMovingDrop]="parentVirtDir" [attr.droppable]="true" id="left" class="igx-grid__scroll-on-drag-pinned" [style.left.px]="pinnedWidth"></span>
46-
<ng-template igxFor let-rowData [igxForOf]="data | gridFiltering:filteringExpressionsTree:id:pipeTrigger
47-
| gridSort:sortingExpressions:id:pipeTrigger" let-rowIndex="index" [igxForScrollOrientation]="'vertical'"
46+
<ng-template igxFor let-rowData [igxForOf]="data | treeGridHierarchizing:childDataKey:id:pipeTrigger | treeGridFlattening:id:pipeTrigger"
47+
let-rowIndex="index" [igxForScrollOrientation]="'vertical'"
4848
[igxForContainerSize]='calcHeight' [igxForItemSize]="rowHeight" #verticalScrollContainer (onChunkPreload)="dataLoading($event)">
4949
<ng-template #record_template>
50-
<igx-tree-grid-row [gridID]="id" [index]="rowIndex" [rowData]="rowData" #row>
50+
<igx-tree-grid-row [gridID]="id" [index]="rowIndex" [flatRow]="rowData" #row>
5151
</igx-tree-grid-row>
5252
</ng-template>
5353

projects/igniteui-angular/src/lib/tree-grid/tree-grid.component.ts

+10
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,16 @@ export class IgxTreeGridComponent extends IgxGridBaseComponent {
7171
}
7272
}
7373

74+
/**
75+
* An @Input property that sets the child data key of the `IgxTreeGridComponent`.
76+
* ```html
77+
* <igx-tree-grid #grid [data]="localData" [showToolbar]="true" [childDataKey]="employees" [autoGenerate]="true"></iigx-tree-grid>
78+
* ```
79+
* @memberof IgxTreeGridRowComponent
80+
*/
81+
@Input()
82+
public childDataKey;
83+
7484
private gridAPI: IgxTreeGridAPIService;
7585

7686
constructor(

projects/igniteui-angular/src/lib/tree-grid/tree-grid.module.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,22 @@ import { IgxTreeGridRowComponent } from './tree-grid-row.component';
77
import { IgxChipsModule } from '../chips/chips.module';
88
import { IgxGridCommonModule } from '../grid-common/common/grid-common.module';
99
import { GridBaseAPIService } from '../grid-common';
10+
import { IgxTreeGridHierarchizingPipe } from './tree-grid.pipes';
11+
import { IgxTreeGridFlatteningPipe } from './tree-grid.pipes';
12+
import { IgxTreeGridCellComponent } from './tree-cell.component';
1013

1114
@NgModule({
1215
declarations: [
1316
IgxTreeGridComponent,
14-
IgxTreeGridRowComponent
17+
IgxTreeGridRowComponent,
18+
IgxTreeGridCellComponent,
19+
IgxTreeGridHierarchizingPipe,
20+
IgxTreeGridFlatteningPipe
1521
],
1622
exports: [
1723
IgxTreeGridComponent,
1824
IgxTreeGridRowComponent,
25+
IgxTreeGridCellComponent,
1926
IgxGridCommonModule
2027
],
2128
imports: [
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import { Pipe, PipeTransform } from '@angular/core';
2+
import { cloneArray } from '../core/utils';
3+
import { DataUtil } from '../data-operations/data-util';
4+
import { IGroupByExpandState } from '../data-operations/groupby-expand-state.interface';
5+
import { IgxTreeGridAPIService } from './tree-grid-api.service';
6+
import { IGridBaseComponent } from '../grid-common/common/grid-interfaces';
7+
import { GridBaseAPIService } from '../grid-common/api.service';
8+
import { IgxTreeGridComponent } from './tree-grid.component';
9+
10+
export interface IHierarchicalRecord {
11+
data: any;
12+
children: IHierarchicalRecord[];
13+
}
14+
15+
export interface IHierarchizedResult {
16+
data: IHierarchicalRecord[];
17+
}
18+
19+
export interface IFlattenedRecord {
20+
data: any;
21+
hasChildren: boolean;
22+
indentationLevel: number;
23+
}
24+
25+
/**
26+
*@hidden
27+
*/
28+
@Pipe({
29+
name: 'treeGridHierarchizing',
30+
pure: true
31+
})
32+
export class IgxTreeGridHierarchizingPipe implements PipeTransform {
33+
private gridAPI: IgxTreeGridAPIService;
34+
35+
constructor(gridAPI: GridBaseAPIService<IGridBaseComponent>) {
36+
this.gridAPI = <IgxTreeGridAPIService>gridAPI;
37+
}
38+
39+
public transform(collection: any[], childDataKey: string,
40+
id: string, pipeTrigger: number): IHierarchizedResult {
41+
const hirerchicalRecords = this.hierarchizeRecursive(collection, childDataKey);
42+
43+
return {
44+
data: hirerchicalRecords
45+
};
46+
}
47+
48+
private hierarchizeRecursive(collection: any[], childDataKey: string): IHierarchicalRecord[] {
49+
const result: IHierarchicalRecord[] = [];
50+
51+
for (let i = 0; i < collection.length; i++) {
52+
const item = collection[i];
53+
result.push({
54+
data: item,
55+
children: item[childDataKey] ? this.hierarchizeRecursive(item[childDataKey], childDataKey) : null
56+
});
57+
}
58+
59+
return result;
60+
}
61+
}
62+
63+
/**
64+
*@hidden
65+
*/
66+
@Pipe({
67+
name: 'treeGridFlattening',
68+
pure: true
69+
})
70+
export class IgxTreeGridFlatteningPipe implements PipeTransform {
71+
private gridAPI: IgxTreeGridAPIService;
72+
73+
constructor(gridAPI: GridBaseAPIService<IGridBaseComponent>) {
74+
this.gridAPI = <IgxTreeGridAPIService>gridAPI;
75+
}
76+
77+
public transform(collection: IHierarchizedResult,
78+
id: string, pipeTrigger: number): any[] {
79+
80+
const grid: IgxTreeGridComponent = this.gridAPI.get(id);
81+
82+
const data: IFlattenedRecord[] = [];
83+
84+
this.getFlatDataRecusrive(collection.data, data, 0);
85+
86+
return data;
87+
}
88+
89+
private getFlatDataRecusrive(collection: IHierarchicalRecord[], data: IFlattenedRecord[] = [], indentationLevel: number) {
90+
91+
if (!collection || !collection.length) {
92+
return;
93+
}
94+
95+
for (let i = 0; i < collection.length; i++) {
96+
const hirarchicalRecord = collection[i];
97+
const flatRecord: IFlattenedRecord = {
98+
data: hirarchicalRecord.data,
99+
indentationLevel: indentationLevel,
100+
hasChildren: hirarchicalRecord.children && hirarchicalRecord.children.length > 0
101+
};
102+
data.push(flatRecord);
103+
this.getFlatDataRecusrive(hirarchicalRecord.children, data, indentationLevel + 1);
104+
}
105+
}
106+
}

src/app/tree-grid/tree-grid.sample.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<div class="sample-content">
88
<div class="sample-column">
9-
<igx-tree-grid #grid1 [data]="data" [rowSelectable]="true" [paging]="false" [width]="'900px'" [height]="'500px'">
9+
<igx-tree-grid #grid1 [data]="data" childDataKey="ChildCompanies" [rowSelectable]="true" [paging]="false" [width]="'900px'" [height]="'500px'">
1010
<igx-column *ngFor="let c of columns" [field]="c.field"
1111
[header]="c.field"
1212
[movable]="c.movable"

0 commit comments

Comments
 (0)