ak-tree-view
v1.0.6
Published
Tree view component for angular
Downloads
143
Maintainers
Readme
Tree View
A tree view component for Angular.
Getting started
Import TreeModule
import { TreeModule } from "ak-tree-view";
@NgModule({
declarations: [AppComponent],
imports: [CommonModule, TreeModule],
bootstrap: [AppComponent],
})
Example
TS file
import { Component, ViewChild } from "@angular/core";
import { FormBuilder, FormGroup } from "@angular/forms";
import {
TreeViewComponent,
TreeConfig,
DropEvent,
TreeNode,
} from "ak-tree-view";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.scss"],
})
export class AppComponent {
@ViewChild(TreeViewComponent) tree!: TreeViewComponent;
readonly STORAGE_KEY = "tree_state";
public config: TreeConfig = {
lazyChildrenLoader: this.getChildren.bind(this),
canDrag: this.canDrag.bind(this),
canDrop: this.canDrop.bind(this),
onCollapse: this.onCollapse.bind(this),
onExpand: this.onExpand.bind(this),
hideToggler: false,
expandAfterDrop: false,
showDragHandler: true,
slotOverTimeOut: 50,
nodePadding: 40,
branchline: true,
branchlinePadding: 15,
};
public nodes = [
{
name: "root1",
isExpanded: false,
children: [{ name: "child1" }, { name: "child2" }],
},
{
name: "root2",
isExpanded: false,
children: [
{ name: "child2.1" },
{ name: "child2.2", children: [{ name: "child2.2.1" }] },
],
},
{ name: "root3", hasLazyChildren: true },
{ name: "root4" },
{ name: "root5", children: [] },
];
public providers = [
{
name: "Folder",
children: [],
},
{
name: "File",
},
];
save(): void {
this.tree.toJSON().then((json) => {
localStorage.setItem(this.STORAGE_KEY, JSON.stringify(json));
alert("state saved to local storage !");
});
}
edit(): void {
this.tree.toggleEditMode();
}
add(): void {
this.tree.addNode({ name: "New node" });
}
update(node: TreeNode): void {
node.data = { name: "New name" };
}
load(): void {
const json = localStorage.getItem(this.STORAGE_KEY);
if (!json) {
return;
}
this.tree.fromJSON(JSON.parse(json));
}
onDrop($event: DropEvent): void {
console.log("Drop event...", $event);
}
getChildren(treeNode: TreeNode): Promise<any[]> {
return new Promise((resolve) => {
// To simulate API call
setTimeout(() => {
resolve(this.nodes);
}, 2000);
});
}
// Example (Optional)
canDrag(treeNode: TreeNode): boolean {
return true;
}
// Example (Optional)
canDrop(treeNode: TreeNode): boolean {
return true;
}
// Example (Optional)
public onCollapse(treeNode: TreeNode): void {
console.log("collapsed", treeNode);
}
// Example (Optional)
public onExpand(treeNode: TreeNode): void {
console.log("expanded", treeNode);
}
}
HTML file
<div class="app-container">
<div class="app-content">
<div class="app-content-buttons">
<button (click)="save()">Save state</button>
<button (click)="load()">load state</button>
<button (click)="edit()">edit mode</button>
<button (click)="add()">add node</button>
</div>
<div class="app-content-tree">
<tree-view
#treeView
[nodes]="nodes"
[config]="config"
(drop)="onDrop($event)"
>
<ng-template #node let-node let-index="index">
<div class="custom-node">
<div class="left">{{ node.data.name }} {{ index }}</div>
<div class="option">
<button (click)="update(node)">Update</button>
</div>
</div>
</ng-template>
<ng-template #loading>
<small>My custom children loading...</small>
</ng-template>
</tree-view>
</div>
</div>
<div class="app-list">
<div class="app-list-providers">
<div
treeNodeToTransfert
[tree]="treeView"
[data]="item"
class="app-list-node"
*ngFor="let item of providers"
>
{{ item.name }}
</div>
</div>
</div>
</div>
SCSS file
tree-view {
position: relative;
z-index: 1;
.tree-node {
&-container {
background: white;
border-radius: 5px;
border: 1px solid rgb(207, 207, 207);
&-left {
display: flex;
align-items: center;
}
}
&-content {
padding: 10px;
}
&-parent {
font-weight: 600;
&:hover {
cursor: pointer;
}
}
}
.custom-node {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
width: 100%;
.option {
&:hover {
cursor: s-resize;
}
}
}
}
.app {
&-container {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-around;
width: 100%;
height: 100%;
}
&-content {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
&-buttons {
margin-bottom: 10px;
button {
margin: 0px 5px;
}
}
&-tree {
background-color: rgb(226, 226, 226);
overflow: auto;
width: 608px;
height: 674px;
position: relative;
padding: 10px;
&-grid {
z-index: 0;
position: absolute;
width: 100%;
height: 100%;
display: flex;
.line {
border-left: 1px solid rgb(202, 202, 202);
margin-left: 40px;
height: 100%;
}
}
}
}
&-list {
background-color: rgb(224, 224, 224);
padding: 20px;
overflow: auto;
width: 208px;
height: 674px;
&-node {
display: flex;
align-items: center;
background-color: white;
border: 1px solid rgb(189, 189, 189);
border-radius: 5px;
padding: 10px;
margin: 5px 0px;
&:hover {
cursor: grab;
}
}
}
}
.indicator {
display: flex;
align-items: center;
justify-content: center;
background-color: orangered;
width: 30px;
height: 41px;
margin-right: 8px;
color: white;
font-weight: bold;
}
.tree-node-drop-slot {
height: 5px;
transition: height 0.25s ease-in;
&.active {
height: 40px !important;
}
}
.tree-view-root.empty {
.tree-node-drop-slot {
height: 40px;
}
}
.option {
display: flex;
align-items: center;
}
.moving-state.dragover {
.tree-node-container {
background: rgba(2, 235, 2, 0.356);
}
}
.dragover .tree-node-container {
background: rgba(2, 235, 2, 0.356);
}