Skip to content

Commit 23fde2b

Browse files
committed
feat(tree): allow specifying key where tree status is saved
1 parent e818477 commit 23fde2b

File tree

6 files changed

+84
-24
lines changed

6 files changed

+84
-24
lines changed

projects/ngx-datatable/src/lib/components/body/body.component.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import { DataTableSummaryRowComponent } from './summary/summary-row.component';
4040
import { DataTableSelectionComponent } from './selection.component';
4141
import { DataTableGhostLoaderComponent } from './ghost-loader/ghost-loader.component';
4242
import { ProgressBarComponent } from './progress-bar.component';
43+
import { getByNestedIndex } from '../../utils/tree';
4344

4445
@Component({
4546
selector: 'datatable-body',
@@ -138,7 +139,7 @@ import { ProgressBarComponent } from './progress-bar.component';
138139
[expanded]="getRowExpanded(group)"
139140
[rowClass]="rowClass"
140141
[displayCheck]="displayCheck"
141-
[treeStatus]="group?.treeStatus"
142+
[treeStatus]="getTreeStatus(group)"
142143
[ghostLoadingIndicator]="ghostLoadingIndicator"
143144
[draggable]="rowDraggable"
144145
[verticalScrollVisible]="verticalScrollVisible"
@@ -172,7 +173,7 @@ import { ProgressBarComponent } from './progress-bar.component';
172173
[expanded]="getRowExpanded(group)"
173174
[rowClass]="rowClass"
174175
[displayCheck]="displayCheck"
175-
[treeStatus]="group?.treeStatus"
176+
[treeStatus]="getTreeStatus(group)"
176177
[ghostLoadingIndicator]="ghostLoadingIndicator"
177178
[draggable]="rowDraggable"
178179
[verticalScrollVisible]="verticalScrollVisible"
@@ -394,6 +395,8 @@ export class DataTableBodyComponent<TRow extends { treeStatus?: TreeStatus } = a
394395

395396
@Input() verticalScrollVisible = false;
396397

398+
@Input() treeStatusKey = 'treeStatus';
399+
397400
@Output() scroll: EventEmitter<ScrollEvent> = new EventEmitter();
398401
@Output() page: EventEmitter<number> = new EventEmitter();
399402
@Output() activate: EventEmitter<ActivateEvent<TRow>> = new EventEmitter();
@@ -958,6 +961,13 @@ export class DataTableBodyComponent<TRow extends { treeStatus?: TreeStatus } = a
958961
return this.rowIndexes.get(row) || 0;
959962
}
960963

964+
/**
965+
* Returns the tree status of the row
966+
*/
967+
getTreeStatus(row: RowOrGroup<TRow>): TreeStatus {
968+
return getByNestedIndex(row, this.treeStatusKey);
969+
}
970+
961971
onTreeAction(row: TRow) {
962972
this.treeAction.emit({ row });
963973
}

projects/ngx-datatable/src/lib/components/datatable.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
[rowDraggable]="rowDraggable"
7474
[rowDragEvents]="rowDragEvents"
7575
[rowDefTemplate]="rowDefTemplate"
76+
[treeStatusKey]="treeStatusKey"
7677
>
7778
<ng-content select="[loading-indicator]" ngProjectAs="[loading-indicator]">
7879
<datatable-progress></datatable-progress>

projects/ngx-datatable/src/lib/components/datatable.component.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,11 @@ export class DatatableComponent<TRow = any>
443443
*/
444444
@Input() treeToRelation: string;
445445

446+
/**
447+
* The key of the row used to store the tree status, can be nested by separating keys with "."
448+
*/
449+
@Input() treeStatusKey = 'treeStatus';
450+
446451
/**
447452
* A flag for switching summary row on / off
448453
*/
@@ -862,7 +867,8 @@ export class DatatableComponent<TRow = any>
862867
this._internalRows = groupRowsByParents(
863868
this._internalRows,
864869
optionalGetterForProp(this.treeFromRelation),
865-
optionalGetterForProp(this.treeToRelation)
870+
optionalGetterForProp(this.treeToRelation),
871+
this.treeStatusKey
866872
);
867873

868874
if (this._rows && this._groupRowsBy) {
@@ -1205,7 +1211,8 @@ export class DatatableComponent<TRow = any>
12051211
this._internalRows = groupRowsByParents(
12061212
this._internalRows,
12071213
optionalGetterForProp(this.treeFromRelation),
1208-
optionalGetterForProp(this.treeToRelation)
1214+
optionalGetterForProp(this.treeToRelation),
1215+
this.treeStatusKey
12091216
);
12101217

12111218
// Always go to first page when sorting to see the newly sorted data
@@ -1306,7 +1313,8 @@ export class DatatableComponent<TRow = any>
13061313
this._internalRows = groupRowsByParents(
13071314
this._internalRows,
13081315
optionalGetterForProp(this.treeFromRelation),
1309-
optionalGetterForProp(this.treeToRelation)
1316+
optionalGetterForProp(this.treeToRelation),
1317+
this.treeStatusKey
13101318
);
13111319
}
13121320
}

projects/ngx-datatable/src/lib/utils/tree.ts

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { getterForProp } from './column-prop-getters';
22
import { TableColumnProp } from '../types/table-column.type';
3+
import { TreeStatus } from '../types/public.types';
34

45
export type OptionalValueGetter = (row: any) => any | undefined;
56
export function optionalGetterForProp(prop: TableColumnProp): OptionalValueGetter {
@@ -45,14 +46,15 @@ export function optionalGetterForProp(prop: TableColumnProp): OptionalValueGette
4546
export function groupRowsByParents<TRow>(
4647
rows: TRow[],
4748
from?: OptionalValueGetter,
48-
to?: OptionalValueGetter
49+
to?: OptionalValueGetter,
50+
statusIndex = 'treeStatus'
4951
): TRow[] {
5052
if (from && to) {
5153
const nodeById = {};
5254
const l = rows.length;
5355
let node: TreeNode | null = null;
5456

55-
nodeById[0] = new TreeNode(); // that's the root node
57+
nodeById[0] = new TreeNode(null, statusIndex); // that's the root node
5658

5759
const uniqIDs = rows.reduce((arr, item) => {
5860
const toValue = to(item);
@@ -64,7 +66,7 @@ export function groupRowsByParents<TRow>(
6466

6567
for (let i = 0; i < l; i++) {
6668
// make TreeNode objects for each item
67-
nodeById[to(rows[i])] = new TreeNode(rows[i]);
69+
nodeById[to(rows[i])] = new TreeNode(rows[i], statusIndex);
6870
}
6971

7072
for (let i = 0; i < l; i++) {
@@ -91,25 +93,60 @@ export function groupRowsByParents<TRow>(
9193
}
9294
}
9395

96+
export const getByNestedIndex = (obj: any, index: string) => {
97+
console.log(obj);
98+
let prop: any = obj;
99+
index.split('.').forEach(indexPart => {
100+
if (prop !== undefined) {
101+
prop = prop[indexPart];
102+
}
103+
});
104+
console.log(prop);
105+
return prop;
106+
};
107+
108+
export const createWithNestedIndex = (index: string, val: any) => {
109+
const rootProp: any = {};
110+
let prop: any = rootProp;
111+
const splitIndex = index.split('.');
112+
splitIndex.forEach((indexPart, index) => {
113+
if (index === splitIndex.length - 1) {
114+
prop[indexPart] = val;
115+
return;
116+
}
117+
if (prop[indexPart] === undefined) {
118+
prop[indexPart] = {};
119+
}
120+
prop = prop[indexPart];
121+
});
122+
return rootProp;
123+
};
124+
94125
class TreeNode {
95126
public row: any;
96127
public parent: any;
97128
public children: any[];
129+
private statusIndex: string;
98130

99-
constructor(row: any | null = null) {
131+
constructor(row: any | null = null, statusIndex = 'treeStatus') {
100132
if (!row) {
101133
row = {
102134
level: -1,
103-
treeStatus: 'expanded'
135+
...createWithNestedIndex(statusIndex, 'expanded')
104136
};
105137
}
106138
this.row = row;
107139
this.parent = null;
108140
this.children = [];
141+
this.statusIndex = statusIndex;
142+
}
143+
144+
get treeStatus(): TreeStatus {
145+
return getByNestedIndex(this.row, this.statusIndex);
109146
}
110147

111148
flatten(f: any, recursive: boolean) {
112-
if (this.row.treeStatus === 'expanded') {
149+
if (this.treeStatus === 'expanded') {
113150
for (let i = 0, l = this.children.length; i < l; i++) {
114151
const child = this.children[i];
115152
f.apply(child, Array.prototype.slice.call(arguments, 2));

src/app/tree/client-tree.component.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { Employee } from '../data.model';
2525
rowHeight="auto"
2626
[treeFromRelation]="'manager'"
2727
[treeToRelation]="'name'"
28+
[treeStatusKey]="'options.treeStatus'"
2829
[rows]="rows"
2930
(treeAction)="onTreeAction($event)"
3031
>
@@ -49,7 +50,7 @@ import { Employee } from '../data.model';
4950
styles: ['.icon {height: 10px; width: 10px; }', '.disabled {opacity: 0.5; }']
5051
})
5152
export class ClientTreeComponent {
52-
rows: (Employee & { treeStatus: TreeStatus })[] = [];
53+
rows: (Employee & { options: { treeStatus: TreeStatus } })[] = [];
5354

5455
ColumnMode = ColumnMode;
5556

@@ -72,10 +73,13 @@ export class ClientTreeComponent {
7273

7374
onTreeAction(event: any) {
7475
const row = event.row;
75-
if (row.treeStatus === 'collapsed') {
76-
row.treeStatus = 'expanded';
76+
if (!row.options) {
77+
row.options = {};
78+
}
79+
if (row.options.treeStatus === 'collapsed') {
80+
row.options.treeStatus = 'expanded';
7781
} else {
78-
row.treeStatus = 'collapsed';
82+
row.options.treeStatus = 'collapsed';
7983
}
8084
this.rows = [...this.rows];
8185
}

src/assets/data/company_tree.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,58 +4,58 @@
44
"gender": "female",
55
"company": "Johnson, Johnson and Partners, LLC CMP DDC",
66
"age": 22,
7-
"treeStatus": "collapsed"
7+
"options": { "treeStatus": "collapsed" }
88
},
99
{
1010
"name": "Claudine Neal",
1111
"gender": "female",
1212
"company": "Sealoud",
1313
"age": 55,
14-
"treeStatus": "disabled"
14+
"options": { "treeStatus": "disabled" }
1515
},
1616
{
1717
"name": "Beryl Rice",
1818
"gender": "female",
1919
"company": "Velity",
2020
"age": 67,
21-
"treeStatus": "disabled"
21+
"options": { "treeStatus": "disabled" }
2222
},
2323
{
2424
"name": "Wilder Gonzales",
2525
"gender": "male",
2626
"company": "Geekko",
27-
"treeStatus": "disabled"
27+
"options": { "treeStatus": "disabled" }
2828
},
2929
{
3030
"name": "Georgina Schultz",
3131
"gender": "female",
3232
"company": "Suretech",
33-
"treeStatus": "collapsed"
33+
"options": { "treeStatus": "collapsed" }
3434
},
3535
{
3636
"name": "Carroll Buchanan",
3737
"gender": "male",
3838
"company": "Ecosys",
39-
"treeStatus": "disabled"
39+
"options": { "treeStatus": "disabled" }
4040
},
4141
{
4242
"name": "Valarie Atkinson",
4343
"gender": "female",
4444
"company": "Hopeli",
45-
"treeStatus": "disabled"
45+
"options": { "treeStatus": "disabled" }
4646
},
4747
{
4848
"name": "Schroeder Mathews",
4949
"gender": "male",
5050
"company": "Polarium",
5151
"manager": "Ethel Price",
52-
"treeStatus": "disabled"
52+
"options": { "treeStatus": "disabled" }
5353
},
5454
{
5555
"name": "Lynda Mendoza",
5656
"gender": "female",
5757
"company": "Dogspa",
5858
"manager": "Georgina Schultz",
59-
"treeStatus": "disabled"
59+
"options": { "treeStatus": "disabled" }
6060
}
6161
]

0 commit comments

Comments
 (0)