Skip to content

Commit

Permalink
refactor(tree-grid): allow specify getters for node properties (#1254)
Browse files Browse the repository at this point in the history
  • Loading branch information
yggg committed Feb 22, 2019
1 parent 3cf29d8 commit a263a2e
Show file tree
Hide file tree
Showing 20 changed files with 342 additions and 108 deletions.
1 change: 0 additions & 1 deletion docs/structure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,6 @@ export const structure = [
icon: 'tree-grid.svg',
source: [
'NbTreeGridComponent',
'NbTreeGridNode',
'NbTreeGridPresentationNode',
'NbTreeGridSortService',
'NbTreeGridFilterService',
Expand Down
6 changes: 6 additions & 0 deletions src/app/playground-components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1301,6 +1301,12 @@ export const PLAYGROUND_COMPONENTS: ComponentLink[] = [
component: 'TreeGridDisableClickToggleComponent',
name: 'Tree Grid Disable Click Toggle',
},
{
path: 'tree-grid-custom-node-structure.component',
link: '/tree-grid/tree-grid-custom-node-structure.component',
component: 'TreeGridCustomNodeStructureComponent',
name: 'Tree Grid Custom Node Structure',
},
],
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import { Injectable } from '@angular/core';
import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
import { map } from 'rxjs/operators';

import { NbDataSource } from '../../cdk/table';
import { NbCollectionViewer } from '../../cdk/collections';
import { NbTreeGridSortService } from './tree-grid-sort.service';
import { NbDataSource } from '../../cdk/table';
import { NbSortable, NbSortRequest } from '../tree-grid-sort.component';
import { NbTreeGridDataService } from './tree-grid-data.service';
import { NbTreeGridFilterService } from './tree-grid-filter.service';
import { NbTreeGridSortService } from './tree-grid-sort.service';
import { NbGetters, NB_DEFAULT_ROW_LEVEL, NbTreeGridPresentationNode } from './tree-grid.model';
import { NbToggleOptions, NbTreeGridService } from './tree-grid.service';
import { NbTreeGridDataService } from './tree-grid-data.service';
import { NbSortable, NbSortRequest } from '../tree-grid-sort.component';
import { DEFAULT_ROW_LEVEL, NbTreeGridNode, NbTreeGridPresentationNode } from './tree-grid.model';

export interface NbFilterable {
filter(filterRequest: string);
Expand All @@ -40,10 +40,12 @@ export class NbTreeGridDataSource<T> extends NbDataSource<NbTreeGridPresentation
super();
}

setData(data: NbTreeGridNode<T>[]) {
const presentationData: NbTreeGridPresentationNode<T>[] = data
? this.treeGridDataService.toPresentationNodes(data)
: [];
setData<N>(data: N[], customGetters?: NbGetters<N, T>) {
let presentationData: NbTreeGridPresentationNode<T>[] = [];
if (data) {
presentationData = this.treeGridDataService.toPresentationNodes(data, customGetters);
}

this.data = new BehaviorSubject(presentationData);
this.updateChangeSubscription();
}
Expand Down Expand Up @@ -81,7 +83,7 @@ export class NbTreeGridDataSource<T> extends NbDataSource<NbTreeGridPresentation

getLevel(rowIndex: number): number {
const row = this.renderData.value[rowIndex];
return row ? row.level : DEFAULT_ROW_LEVEL;
return row ? row.level : NB_DEFAULT_ROW_LEVEL;
}

sort(sortRequest: NbSortRequest) {
Expand Down Expand Up @@ -130,15 +132,15 @@ export class NbTreeGridDataSourceBuilder<T> {
private treeGridDataService: NbTreeGridDataService<T>) {
}

create(data: NbTreeGridNode<T>[]): NbTreeGridDataSource<T> {
create<N>(data: N[], customGetters?: NbGetters<N, T>): NbTreeGridDataSource<T> {
const dataSource = new NbTreeGridDataSource<T>(
this.sortService,
this.filterService,
this.treeGridService,
this.treeGridDataService,
);

dataSource.setData(data);
dataSource.setData(data, customGetters);
return dataSource;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,41 @@
* Copyright Akveo. All Rights Reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*/

import { Injectable } from '@angular/core';

import { DEFAULT_ROW_LEVEL, NbTreeGridNode, NbTreeGridPresentationNode } from './tree-grid.model';
import { NbGetters, NB_DEFAULT_ROW_LEVEL, NbTreeGridPresentationNode } from './tree-grid.model';

@Injectable()
export class NbTreeGridDataService<T> {

toPresentationNodes(nodes: NbTreeGridNode<T>[], level: number = DEFAULT_ROW_LEVEL): NbTreeGridPresentationNode<T>[] {
return nodes.map((node: NbTreeGridNode<T>) => {
const presentationNode = new NbTreeGridPresentationNode(node, level);
private defaultGetters: NbGetters<any, T> = {
dataGetter: node => node.data,
childrenGetter: d => d.children || undefined,
expandedGetter: d => !!d.expanded,
};

toPresentationNodes<N>(
nodes: N[],
customGetters?: NbGetters<N, T>,
level: number = NB_DEFAULT_ROW_LEVEL,
): NbTreeGridPresentationNode<T>[] {
const getters: NbGetters<N, T> = { ...this.defaultGetters, ...customGetters };

return this.mapNodes(nodes, getters, level);
}

if (node.children) {
presentationNode.children = this.toPresentationNodes(node.children, level + 1);
private mapNodes<N>(nodes: N[], getters: NbGetters<N, T>, level: number): NbTreeGridPresentationNode<T>[] {
const { dataGetter, childrenGetter, expandedGetter } = getters;

return nodes.map(node => {
const childrenNodes = childrenGetter(node);
let children: NbTreeGridPresentationNode<T>[];
if (childrenNodes) {
children = this.toPresentationNodes(childrenNodes, getters, level + 1);
}

return presentationNode;
return new NbTreeGridPresentationNode(dataGetter(node), children, expandedGetter(node), level);
});
}

Expand All @@ -36,14 +55,11 @@ export class NbTreeGridDataService<T> {

copy(nodes: NbTreeGridPresentationNode<T>[]): NbTreeGridPresentationNode<T>[] {
return nodes.map((node: NbTreeGridPresentationNode<T>) => {
const presentationNode = new NbTreeGridPresentationNode(node.node, node.level);
presentationNode.expanded = node.expanded;

let children: NbTreeGridPresentationNode<T>[];
if (node.hasChildren()) {
presentationNode.children = this.copy(node.children);
children = this.copy(node.children);
}

return presentationNode;
return new NbTreeGridPresentationNode(node.data, children, node.expanded, node.level);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export class NbTreeGridFilterService<T> {
if (filteredChildren && filteredChildren.length) {
node.expanded = true;
filtered.push(node);
} else if (this.filterPredicate(node.node.data, query)) {
} else if (this.filterPredicate(node.data, query)) {
filtered.push(node);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,52 +4,33 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*/

/**
* Table's data interface
*/
export interface NbTreeGridNode<T> {
/**
* Data object which will be available as a context of rows and cell templates
* @type T
*/
data: T,
/**
* Child rows
*/
children?: NbTreeGridNode<T>[];
/**
* Row expand state
*/
expanded?: boolean;
}
export const NB_DEFAULT_ROW_LEVEL: number = 0;

export type NbDataGetter<N, T> = (N) => T;
export type NbChildrenGetter<N, T> = (N) => (T[] | undefined);
export type NbExpandedGetter<N> = (N) => boolean;

export const DEFAULT_ROW_LEVEL: number = 0;
export interface NbGetters<N, T> {
dataGetter?: NbDataGetter<N, T>;
childrenGetter?: NbChildrenGetter<N, T>;
expandedGetter?: NbExpandedGetter<N>;
}

/**
* Implicit context of cells and rows
*/
export class NbTreeGridPresentationNode<T> {
/**
* Row expand state
*/
get expanded(): boolean {
return this.node.expanded;
}
set expanded(value: boolean) {
this.node.expanded = value;
}
children: NbTreeGridPresentationNode<T>[] = [];

/**
* Data object associated with row
*/
get data(): T {
return this.node.data;
}

constructor(
readonly node: NbTreeGridNode<T>,
public readonly level: number = DEFAULT_ROW_LEVEL,
/**
* Data object associated with row
*/
public readonly data: T,
public children: NbTreeGridPresentationNode<T>[] | undefined,
/**
* Row expand state
*/
public expanded: boolean,
public readonly level: number,
) {}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export class NbTreeGridService<T> {
const toCheck: NbTreeGridPresentationNode<T>[] = [...data];

for (const node of toCheck) {
if (node.node.data === row) {
if (node.data === row) {
return node;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import {
import { NB_TREE_GRID } from './tree-grid-injection-tokens';
import { NbTreeGridComponent } from './tree-grid.component';
import { NbTreeGridColumnDefDirective } from './tree-grid-column-def.directive';
import { DEFAULT_ROW_LEVEL } from './data-source/tree-grid.model';
import { NB_DEFAULT_ROW_LEVEL } from './data-source/tree-grid.model';
import { NbColumnsService } from './tree-grid-columns.service';

@Directive({
Expand Down Expand Up @@ -121,7 +121,7 @@ export class NbTreeGridCellDirective extends NbCellDirective implements OnInit,

private getStartPadding(): string | SafeStyle | null {
const rowLevel = this.tree.getCellLevel(this, this.columnDef.name);
if (rowLevel === DEFAULT_ROW_LEVEL) {
if (rowLevel === NB_DEFAULT_ROW_LEVEL) {
return null;
}

Expand Down

0 comments on commit a263a2e

Please sign in to comment.