An angular tree component with drag and drop.
npm install @cluetec/ngcx-treeA reusable tree component for Angular based on the CDK Tree and the CDK Drag n
Drop features.
Includes only peer dependencies to angular cdk, no other library included. So
the lib size is pretty small.
https://cluetec.github.io/ngcx-tree-demo
- Highly custumizable tree component
- Configure your Angular Template for node rendering
- Or configure your own component for node rendering
- Selection state
- configure which nodes are selectable
- Drag and Drop
- configure which nodes may be moved
- configure where a node can be dropped
- Events (always with detailed information about parents, next or prev. nodes):
- On move
- On click
- On select/unselect
- custom event may be emitted by custom component
Missing features? Let me know :)
- Demo:
- Feature Overview
- Table of Content
- Getting Started
- Prerequisites
- Inputs
- Outputs
- Model
- NgcxTreeConfig
- NgcxTreeNode
- NgcxTreeNodeWrapper
- NgcxTreeNodeMovedEvent
- NgcxCustomComponent
- Input
- Output
- TreeControl - Api
- treeControl
- Additional Helper methods
- selectNodeById
- findNodeById
- Styling
- Include Styles
- CSS Variables
- Common styling
- Dotted tree lines
- Selection highlighting
- Icon color
- Prevent drop reason tooltip
- Font Awesome
- Selection
- Simple Sample
- Contributions
- Samples
1. Install the library:
```
npm install @cluetec/ngcx-tree
2. Import the component. Since it is standalone, either add it directly to
another standlone component or import it into your existing NgModule:
`ts
import { NgcxTreeComponent } from '@cluetec/ngcx-tree';
@Component({
standalone: true,
imports: [NgcxTreeComponent],
})
`
`ts
import { NgcxTreeComponent } from '@cluetec/ngcx-tree';
@NgModule({
declarations: [AppComponent],
imports: [NgcxTreeComponent],
bootstrap: [AppComponent],
})
export class AppModule {}
`
`html`
You need at least angular 16 to use the tree.
| Property | Type | required | Description |
| -------- | --------------------------------- | -------- | ------------------------------------------------------------------- |
| nodes | NgcxTreeNode[] | no | list of nodes to show in the tree |
| config | NgcxTreeConfig | no | used to render the node when no custom template or component is set |
| Property | event content type | Description |
| ----------- | ------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| nodeMoved | NgcxTreeNodeMovedEvent | fired when a node is moved |
| customEvent | any | may be fired by your own custom component |
| clickEvent | NgcxTreeNodeWrapper | fired when node is clicked |
| selectEvent | NgcxTreeNodeWrapper | fired when node is selected or un-selected. Clicking a selected node un-selects the node. |
The component includes a model called NgcxTreeConfig with some basic optional
settings.
- allowDrag method that decides if a node can be dragged:(node: NgcxTreeNodeWrapper
- all nodes are draggable byallowDrop
default
- method that decides if node can be dropped into another node(node: NgcxTreeNodeWrapper
-preventDropReason
every node may be draggable everywhere by default.
- method that decides if node can be dropped into another(node: NgcxTreeNodeWrapper
node
-allowDrop
every node may be draggable everywhere by default. If a non empty string is
returned, then the node cannot be dropped and the string will be displayed.
One of the methods or preventDropReason is sufficient to preventallowSelection
the node to be dropped.
- method that decides if node can be selected(node: NgcxTreeNodeWrapper
- nodes are not selectable bytreeNodeContentTemplate
default
- Angular TemplateRef that will be used to render alet-nodeWrapper="nodeWrapper"
node
may be used to access the nodetreeNodeContentComponent
wrapper to render the node
- Angular Component that will be used to render atreeNodeContentComponent
node. (use or treeNodeContentTemplate, but not
both). see NgcxCustomComponent
If no data is passed to the component, it will simply display some mock data.
Data is provided to the tree in the following format:
| Property | Type | required | Description |
| -------- | -------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| id | string | yes | necessary unique id of the node |
| title | string | no | used to render the node when no custom template or component is set |
| faIcon | string | no | font awesome icon used to render the node when no custom template or component is set. You must include fontawesome on your own if you want |
| children | NgcxTreeNode[] | no | children of the node |
Generic T is the same as the elements of the input nodes.
| Property | Type | Description |
| ------------ | ----------------------------------- | ------------------------------------------------------------------------------------------ |
| id | string | same as NgcxTreeNode.id |
| data | T | data of the input nodes nodes |
| depth | number | depth in the tree starting with 0 |
| index | number | index of the node in it's parent |
| isSelectable | boolean | if the node is selectable. Depending on the config.allowSelection method. (default: false) |
| isFirstChild | boolean | is first node from the same parent |
| isLastChild | boolean | is last node from the same parent |
| children | NgcxTreeNodeWrapper
| parent | NgcxTreeNodeWrapper
| next | NgcxTreeNodeWrapper
| previous | NgcxTreeNodeWrapper
| Property | Type | Description |
| ---------- | ----------------------------------- | ---------------------------------- |
| node | NgcxTreeNodeWrapper
| parent | NgcxTreeNodeWrapper
| afterNode | NgcxTreeNodeWrapper
| beforeNode | NgcxTreeNodeWrapper
Your component can implement this interface and can be set as
Type in the config.treeNodeContentComponent input.
nodeWrapper the input to render the node. Type: NgcxTreeNodeWrapper
customEvent EventEmitter can be used to trigger the output
'customEvent'
Access api like this
``ts
import { ViewChild, Component } from '@angular/core';
import { NgcxTreeComponent, NgcxTreeNode } from '@cluetec/ngcx-tree';
@Component({
selector: 'app-expand-tree-sample',
template: ``
,
standalone: true,
imports: [NgcxTreeComponent],
})
export class ExpandTreeSampleComponent {
nodes = [];
@ViewChild('tree', { static: false })
ngcxTree: NgcxTreeComponent
expandAll(): void {
this.ngcxTree.treeControl.expandAll();
}
}
``
The treeControl extends the treeControl from Angular CDK
(NestedTreeControl) and can mainly be used to
expand and collapse nodes.
Can be called to select a node by id. the selectEvent event is fired afterwards.
Can be used to get the NgcxTreeNodeWrapper for an id. returns undefined
if no node is available for the id.
styles.scss and styles.css contains all the parts described below in one file:
`scss`
@import 'node_modules/@cluetec/ngcx-tree/styles/styles';
Css Variables may be defined to customize the Look and feel like this:
`scss`
--ngcx-tree-color-no-drop: #ff0000;
| Variable name | Description |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ngcx-tree-color-no-drop | Color which is shown at the drop box dashed border or line to indicate that drop is not possible here. You may set to transparent if you don't want the border in this case |
you should set the width of cdk-drop-list to auto, otherwise, the node content
may be on wrong place:
`css`
.ngcx-tree .cdk-drop-list {
width: auto;
}
Or Include this:
`scss`
@import 'node_modules/@cluetec/ngcx-tree/styles/ngcx-common';
Import or copy the scss to show tree lines:
`scss`
@import 'node_modules/@cluetec/ngcx-tree/styles/ngcx-doted-tree-line';
Import or copy the scss to show some selection styling:
`scss`
@import 'node_modules/@cluetec/ngcx-tree/styles/ngcx-selection';
Import or copy the scss to set the color of the node icon:
`scss`
@import 'node_modules/@cluetec/ngcx-tree/styles/ngcx-icon-color';
Import or copy the scss to style the tooltip, shown when config.preventDropReason is used:
`scss`
@import 'node_modules/@cluetec/ngcx-tree/styles/ngcx-tooltip';
Font Awesome is not included here, but to show icons for the nodes you may
include font-awesome on your own and may use the node.faIcon property to set
the icon.
Include like this:
projects/ngcx-tree/stories/styles/styles.scss
Selected node can be styled like this:
`css`
.tree-node-content-container.selected .tree-node-content {
background-color: #555;
padding-left: 5px;
}
Hover effect on selectable node:
`css`
.ngcx-tree:not(.dragging)
.tree-node-content-container.is-selectable:hover
.tree-node-content {
background-color: #fbfbfb;
}
Remove Selection css on dragging element:
`css`
.cdk-drag-preview .tree-node-content-container.selected .tree-node-content {
background-color: inherit;
}
`ts
import { Component } from '@angular/core';
import { NgcxTreeComponent } from '@cluetec/ngcx-tree';
@Component({
selector: 'app-simple-tree-sample',
template: '
standalone: true,
imports: [NgcxTreeComponent],
})
export class SimpleTreeSampleComponent {
nodes = [
{
id: 'fru',
title: 'Fruit',
children: [
{
id: 'app',
title: 'Apple',
},
{
id: 'ban',
title: 'Banana',
},
],
},
{
id: 'fish',
title: 'Fish',
},
];
}
`
Contributions and improvement suggestions are always welcome!
You can run Storybook and see the samples there.
1. npm run buildnpm run storybook`
2.