Smart Tree
Please note the all versions from @smartbit4all/tree^2.0.0
are not backward compatible!
Stable versions:
References
These packages must be updated in case of a new version:
- There are no references yet
How to use
Installation
Go to your project, open the terminal and use the following command:
npm i @smartbit4all/tree
Then import it in the AppModule:
app.module.ts:
import { SmarttreeModule } from '@smartbit4all/tree';
...
@NgModule({
declarations: [...]
imports: [
...
SmarttreeModule,
],
providers: [
...
SmarttreeService,
TreeService
]
...
})
Usage
terminal:
>>> cd src/app
>>> mkdir services
>>> cd ./services
>>> ng g s tree
First option: Create a custom inheritance of the SmarttreeService
:
tree.service.ts:
@Injectable({
providedIn: 'root'
})
export class MainTreeService extends SmarttreeService<SmartTreeModel> {
constructor(
private apiService: BffApiTreeService
) {
super();
}
override async downloadTree(): Promise<SmartTreeModel> {
const treeModel = await this.apiService.getRootNodes().toPromise();
if (!treeModel) {
throw new Error('TreeModel is undefined!');
}
return treeModel;
}
override async downloadChildren(parentNode: SmartTreeNode): Promise<SmartTreeModel> {
const children = await this.apiService.getChildrenNodes(parentNode).toPromise();
if (!children) {
throw new Error(`Node with uri ${parentNode.identifier} does not have children.`);
}
return children;
}
override onTreeNodeClick(treeNode: SmartTreeNode): void {
// Handle tree node click
}
override onTreeNodeOpen(treeNode: SmartTreeNode): void {
if (treeNode.expanded && treeNode.childrenNodes && treeNode.childrenNodes.length) {
treeNode.expanded = false;
await this.apiService
.nodeClosed({ identifier: treeNode.identifier! })
.toPromise()
.then(() => {
this.downloadTree().then((tree) => {
this.treeFromBackend = tree;
this.syncTree();
});
});
return;
}
await this.downloadChildren(treeNode).then((children: SmartTreeNode[]) => {
treeNode.expanded = true;
treeNode.children = children.nodes;
this.syncTree();
});
}
actionLabelTranslator(code: string): string {
// Return a readable version of the code
// Example:
// code: addUser
// return: Add user
}
override syncTree(): void {
if (!this.treeFromBackend) {
throw new Error('There is no treeFromBackend available!');
}
if (!this.smartTreeModel) {
this.smartTreeModel = {
navigationUrlsByNodeType: [],
rootNodes: []
};
}
let smartTreeNodes: SmartTreeNode[] = this.treeFromBackend.nodes.map((node: SmartTreeNode) => {
if (node.actions && node.actions.length) {
// The buttons are customizable
// Example:
let button: SmartTreeNodeButton = {
type: SmartTreeNodeButtonType.MENU,
icon: 'more_vert',
menuItemButtons: node.actions.map((action: UiAction) => {
type: SmartTreeNodeButtonType.NORMAL,
label: this.actionLabelTranslator(action.code),
callback: this.doAction.bind(this),
args: [action, node.identifier]
}),
}
node.button = button;
}
})
// Choose from the followings:
// #1 set up custom buttons
this.smartTreeModel.rootNodes = this.setButtonsForTreeNodes(this.treeFromBackend.rootNodes);
// #2 use the tree without custom buttons
this.smartTreeModel.rootNodes = this.treeFromBackend.rootNodes;
this.findSelected(this.smartTreeModel.rootNodes);
this.smartTreeModelChanged.next(this.smartTreeModel);
}
// This function is not mandatory and also not defined in the SmarttreeService<T>!
// The setButtonsForTreeNodes(rootNodes: SmartTreeNode[]) is just a recommendation, place it
// into your custom TreeService or into a util file.
setButtonsForTreeNodes(rootNodes: SmartTreeNode[]): SmartTreeNode[] {
let smartTreeNodes: SmartTreeNode[] = [];
rootNodes.map((node: SmartTreeNode) => {
if (node.actions && node.actions.length) {
// The buttons are customizable
// Example usage:
let button: SmartTreeNodeButton = {
type: SmartTreeNodeButtonType.MENU,
icon: 'more_vert',
menuItemButtons: node.actions.map((action: UiAction) => {
type: SmartTreeNodeButtonType.NORMAL,
label: this.actionLabelTranslator(action.code),
callback: this.doAction.bind(this),
args: [action, node.identifier]
}),
}
node.button = button;
}
if (node.childrenNodes) {
node.childrenNodes = this.setButtonsForTreeNodes(node.childrenNodes);
}
smartTreeNodes.push(node);
})
return smartTreeNodes;
}
// Feel free to choose from the followings:
// First option
doAction(action: UiAction, identifier: string, args?: any[]): void { ... }
// Second option
doAction(args: any[]): void { ... }
}
Second option: Create a custom inheritance of the SmarttreeGenericService
:
export class MainTreeService extends SmarttreeGenericService {
constructor(
viewContext: SmartViewContextService,
treeService: TreeService,
) {
super(viewContext, treeService);
// Example data
this.configureTree({
pageName: Pages.Main,
treeid: `model.tree`,
viewContextName: Pages.VIEW_CONTEXT
});
}
override getLabelByAction(action: UiAction): string {
return getActionTranslator(action.code!).title;
}
override async doAction(args: any[]): Promise<void> {
let uiAction: UiAction = args[0];
let nodeUuid: string = args[1];
// Do action...
}
}
app.component.html:
<smart-tree [treeStyle]="treeStyle!" [treeService]="treeService"></smart-tree>
app.component.ts:
export class AppComponent {
treeStyle?: TreeStyle;
constructor(public treeService: MainTreeService) {
// set up the BffApiTreeService (headers and url)
this.treeService.initialize();
this.treeStyle = {
levelBackgroundColor: ['rgba(34, 107, 193, 0.3)', 'rgba(0, 0, 0, 0.15)'],
activeStyle: {
backgroundColor: '#1A5DBE',
color: '#FFF'
}
};
}
}
Version logs
@smartbit4all/tree v2.1.12
Type: Update
The SmarttreeService<T>
got a new property: errorMessage: string.
This error message will appear when the tree is not available.
@smartbit4all/tree v2.1.2
Type: Update
From now on the backend's responsibility to handle clicking on an already selected node.
@smartbit4all/tree v2.1.1
Type: Update
In this update a generic tree service has been added to the package.
@smartbit4all/tree v2.0.1
Type: Update
@smartbit4all/icon
support.
@smartbit4all/tree v2.0.0
Type: Major update
The tree requires a new SmartTreeModel
from the backend with the changed SmartTreeNode
s:
export interface SmartTreeModel {
identifier?: string;
rootNodes?: Array<SmartTreeNode>;
}
export interface SmartTreeNode {
identifier?: string;
icon?: string;
caption?: string;
classes?: Array<string>;
hasChildren?: boolean;
childrenNodes?: Array<SmartTreeNode>;
expanded?: boolean;
selected?: boolean;
level?: number;
shortDescription?: string;
nodeType?: string;
button?: object;
actions?: Array<UiAction>;
}
SmartreeService changes:
-
SmarttreeService<T, N>
->SmarttreeService<T>
- The
convertRootNodesToSmartTreeNodes(rootNodes: Array<N>)
function has been removed.
@smartbit4all/tree v1.1.4
Type: Bugfix
Click event on customly defined button was not stopped from propagation.
@smartbit4all/tree v1.1.1
Type: Bugfix
A bug has been fixed which caused that the tree could only expand the root nodes of the tree.
@smartbit4all/tree v1.1.0
Type: Feature
This update contains two changes:
- SmartForm treeStyle before this update could not set the styling of the root nodes. From now the root nodes styling can be setted too.
- SmartTreeNode interface has been extended with a new SmartTreeNodeButton typed property. With this property you can define and add buttons to every treeNode and define the callback functions.
How to use the features of this update:
-
TreeStyle: levelBackground is an array contains the colors in string. The index of an element refers to the level of the treeNode
this.treeStyle = { levelBackgroundColor: ['rgba(34, 107, 193, 0.3)', 'rgba(0, 0, 0, 0.15)'], activeStyle: { backgroundColor: '#1A5DBE', color: '#FFF' } };
-
SmartTreeNodeButton: add button property to the treeNode object. SmartTreeNodeButton has 3 different type:
- ICON
- MENU
- NORMAL
@smartbit4all/tree v1.0.1
Type: Update
The package has been published.
@smartbit4all/tree v0.1.0
Type: Feature
The usage of tree
has been redesigned in order to support the BFF APIs.
New things in this update:
SmarttreeServiceDescriptor<T, N>
export class SmarttreeService<T, N> implements SmarttreeServiceDescriptor<T, N>
Things that have been changed:
-
SmarttreeComponent
does not require aSmarttreeModel
anymore -
SmarttreeComponent
requires an inheritance of theSmarttreeService
- Node click events are no longer handled by the component
- Node click events can be handled manually in the inheritance of the
SmarttreeService
@smartbit4all/tree v0.0.8
Type: Feature
This version contains a routing update, which allows you to navigate to a named outlet.
The change:
The navigationUrl
property of the SmartTreeNodeType
has changed from string to any[].
export interface SmartTreeNodeType {
nodeType: string;
navigationUrl: any[];
}
@smartbit4all/tree v0.0.7
Type: Bugfix
A bug has been fixed which caused routing problems while navigating with objectUri.
The change itself: this.router.navigate(['${navigationUrlByNodeType.navigationUrl}'], { queryParams: { uri: node.objectUri }});
@smartbit4all/tree v0.0.6
Type: Bugfix
The last deselected node could not be selected directly.
@smartbit4all/tree v0.0.5
Type: Bugfix
There were no option to deselect an already selected tree node.
@smartbit4all/tree v0.0.4
Type: Bugfix
Navigating on node click was not working properly.
this.router.navigateByUrl
has been replaced with this.router.navigate
.
@smartbit4all/tree v0.0.3
Type: Feature
The generated TreeModel has been replaced with SmartTreeModel.
The new SmartTreeModel and SmartTreeNode have new features like setting the node type and its navigation target. Also some optional fields have been changed to required ones.