ng2-tree
【转】https://github.com/valor-software/ng2-tree#eyes-demo demo:http://valor-software.com/ng2-tree/
🌿 ng2-tree
ng2-tree is a simple Angular 2 component for visualizing data that can be naturally represented as a tree.
- 🎬 Usage
- 👀 Demo
- 🔧 API
- Changes that should be taken into account in order to migrate from ng2-tree V1 to ng2-tree V2
🎬 Usage
Ok, let's start with an installation - all you need to do is:
npm install --save ng2-tree
Now when you have ng2-tree
installed, you are in a few steps from having tree in your application:
- Add the
TreeModule
to your application's moduleimports
section:
import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { BrowserModule } from '@angular/platform-browser'; import { TreeModule } from 'ng2-tree'; @NgModule({ declarations: [MyComponent], imports: [BrowserModule, TreeModule], bootstrap: [MyComponent] }) export class MyModule { }
- As soon as the previous step is done we need to give ng2-tree a model to render - this can be accomplished by populating its
[tree]
attribute with an object that conforms to theTreeModel
interface (see API):
// 1 - import required classes and interfaces import { TreeModel } from 'ng2-tree'; @Component({ selector: 'myComp', // 2 - set [tree] attribute to tree object template: `<tree [tree]="tree"></tree>` }) class MyComponent { // 3 - make sure that tree object conforms to the TreeModel interface public tree: TreeModel = { value: 'Programming languages by programming paradigm', children: [ { value: 'Object-oriented programming', children: [ {value: 'Java'}, {value: 'C++'}, {value: 'C#'}, ] }, { value: 'Prototype-based programming', children: [ {value: 'JavaScript'}, {value: 'CoffeeScript'}, {value: 'Lua'}, ] } ] }; }
- Apart from that, in order to have usable tree in the browser, you need to add ng2-tree styles which you can find in your
node_modules/ng2-tree/styles.css
- And finally, I suppose, you'd want to listen to events generated by ng2-tree (for a full list of supported events look at the API). No problem, this is also easy to do - for example let's add a listener for
node was selected
kind of events:
// 1 - import required classes and interfaces import { TreeModel, NodeEvent } from 'ng2-tree'; @Component({ selector: 'myComp', // 2 - listent for nodeSelected events and handle them template: `<tree [tree]="tree" (nodeSelected)="logEvent($event)"></tree>` }) class MyComponent { public tree: TreeModel = { ... }; // 3 - print caught event to the console public logEvent(e: NodeEvent): void { console.log(e); } }
Voila! That's pretty much it - enjoy 😊
👀 Demo
Feel free to examine the demo and its sources to find out how things are wired. Also there is another demo built with Angular CLI.
🔧 API
Here is the fully stuffed tree tag that you can use in your templates:
<tree [tree]="tree" [settings]="settings" (nodeRemoved)="handleRemoved($event)" (nodeRenamed)="handleRenamed($event)" (nodeSelected)="handleSelected($event)" (nodeMoved)="handleMoved($event)" (nodeCreated)="handleCreated($event)"> </tree>
Let's go through every element of this structure one by one.
tree
tree
is the selector for TreeComponent
which is bundled into TreeModule
:
[tree]
tree
has a [tree]
attribute which needs to be populated with an object implementing TreeModel
interface. You can import this interface like below:
import { TreeModel } from 'ng2-tree';
Here is the definition of the TreeModel
interface:
interface TreeModel { value: string | RenamableNode; children?: Array<TreeModel>; loadChildren?: ChildrenLoadingFunction; settings?: TreeModelSettings; }
As you can see - object that conforms to this interface has a recursive nature, example can be seen below:
{ value: 'Programming languages by programming paradigm', children: [ { value: 'Object-oriented programming', children: [ {value: 'Java'}, {value: 'C++'}, {value: 'C#'}, ] }, { value: 'Prototype-based programming', children: [ {value: 'JavaScript'}, {value: 'CoffeeScript'}, {value: 'Lua'}, ] } ] }
Property value
can be of type string
or RenamableNode
. RenamableNode
gives you an additional control over the way node is renamed and rendered (by rendered I mean its text representation). Here is the definition of the RenamableNode
interface:
interface RenamableNode { // This method will be invoked in order to apply new value to this kind of node setName(name: string): void; // This method will be invoked in order to get a text for rendering as a node value toString(): string; }
Here is an example of such a node in the TreeModel
object:
{ value: 'Programming languages by programming paradigm', children: [ { value: 'Object-oriented programming', children: [ { // I am a RenamableNode. Yeah, that's me :) value: <RenamableNode>{ name: 'Java', setName(name: string): void { this.name = name; }, toString(): string { return this.name; } } }, {value: 'C++'}, {value: 'C#'}, ] }, { value: 'Prototype-based programming', loadChildren: (callback) => { setTimeout(() => { callback([ {value: 'JavaScript'}, {value: 'CoffeeScript'}, {value: 'TypeScript'}, ]); }, 5000); } } ] };
Load children asynchronously
Another worth noting thing is loadChildren
. This function on TreeModel
allows you to load its children asynchronously.
{ value: 'Prototype-based programming', loadChildren: (callback) => { setTimeout(() => { callback([ {value: 'JavaScript'}, {value: 'CoffeeScript'}, {value: 'TypeScript'}, ]); }, 5000); } }
Node that defines this function is collapsed by default. At the moment of clicking 'Expand' arrow it starts loading its children by calling given function. If loadChildren
function is given to the node - children
property is ignored. For more details - have a look at the Demo.
Configure node via TreeModelSettings
Apart from that TreeModel
interface has an optional field called settings
of type TreeModelSettings
.
Here is an example of its usage:
{
value: 'Prototype-based programming',
settings: {
'static': true
},
children: [
{value: 'JavaScript'},
{value: 'CoffeeScript'},
{value: 'Lua'},
]
}
Right now only one option is supported - static
. This option makes it impossible to drag a tree or modify it in a some way, though you still can select nodes in the static tree and appropriate events will be generated. static
option that's defined on a parent
is automatically applied to its children. If you don't want to make static
all the children, then you can override settings
of the child node.
[settings]
Object that should be passed to [settings]
must be of type Ng2TreeSettings
. This attribute is optional. Right now only one setting is available in there - rootIsVisible
. This setting allows you to make a root node of the tree invisible:
const treeSettings: Ng2TreeSettings = { rootIsVisible: false }
By default rootIsVisible
equals to true
Tree
class
Also in the next section you'll be reading about events generated by the ng2-tree
. And here Tree class comes in handy for us, because its instances propagated with event objects. Under the hood ng2-tree
wraps a TreeModel
provided by the user in Tree
. And Tree
in turn has lots of useful methods and properties (like parent
, hasChild()
, isRoot()
etc.)
events (nodeMoved, nodeSelected, nodeRenamed, nodeRemoved, nodeCreated)
Here is the diagram that shows tree events' hierarchy
NodeEvent
is the root of the tree events' hierarchy. It defines property node
that contains a receiver of the event action (node
is an instance of the Tree
class).
NodeDestructiveEvent
is the parent for all events that cause changes to the structure of the tree or to the node's value.
NodeSelectedEvent
You can subscribe to the NodeSelectedEvent
by attaching listener to the (nodeSelected)
attribute
<tree [tree]="tree" (nodeSelected)="handleSelected($event)"> </tree>
NodeSelectedEvent
has just one property node
which contains a Tree
object representing selected node.
{node: <Tree>{...}}
NodeMovedEvent
You can subscribe to NodeMovedEvent
by attaching listener to (nodeMoved)
attribute
<tree [tree]="tree" (nodeMoved)="handleMoved($event)"> </tree>
NodeMovedEvent
has two properties node
and previousParent
both of which contain Tree
objects:
node
contains a moved node;previousParent
contains a previous parent of the moved node;
{node: <Tree>{...}, previousParent: <Tree>{...}}
NodeRemovedEvent
You can subscribe to NodeRemovedEvent
by attaching listener to (nodeRemoved)
attribute
<tree [tree]="tree" (nodeRemoved)="handleRemoved($event)"> </tree>
NodeRemovedEvent
has a node
property, which contains removed node (of type Tree
).
{node: <Tree>{...}}
NodeCreatedEvent
You can subscribe to NodeCreatedEvent
by attaching listener to (nodeCreated)
attribute
<tree [tree]="tree" (nodeCreated)="handleCreated($event)"> </tree>
NodeCreatedEvent
has a node
property of type Tree
, which contains a created node.
{node: <Tree>{...}}
NodeRenamedEvent
You can subscribe to NodeRenamedEvent
by attaching listener to (nodeRenamed)
attribute
<tree [tree]="tree" (nodeRenamed)="handleRenamed($event)"> </tree>
NodeRenamedEvent
has three properties:
node
contains node that was renamed (instance ofTree
).oldValue
contains a value, that node used to have (it might bestring
orRenamableNode
)newValue
contains a new value of the node (it might bestring
orRenamableNode
)
{ node: <Tree>{...}, oldValue: <string|RenamableNode>{...}, newValue: <string|RenamableNode>{...} }
Changes that should be taken into account in order to migrate from ng2-tree V1 to ng2-tree V2
- Events were reworked:
- In V1 all events that were inherited from NodeDestructiveEvent used to have property
parent
. It's not the case anymore. If you need a parent you should get it fromnode
in event object likenode.parent
; - All events used to have
node
property of typeTreeModel
. Nownode
is of type Tree (as well asnode.parent
); NodeMovedEvent
now has propertypreviousParent
, which contains tree in which moved node used to be.
- In V1 all events that were inherited from NodeDestructiveEvent used to have property
- CSS styles in ng2-tree V2 are distributed as separate file which you can find in
node_modules/ng2-tree/styles.css
. That allows you to override ng2-tree styles more easely.
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· PPT革命!DeepSeek+Kimi=N小时工作5分钟完成?
· What?废柴, 还在本地部署DeepSeek吗?Are you kidding?
· DeepSeek企业级部署实战指南:从服务器选型到Dify私有化落地
· 程序员转型AI:行业分析