Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(tree-grid): allow specify getters for node properties #1254

Merged
merged 7 commits into from
Feb 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading