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:
TreeModule
to your application's module imports
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 {}
[tree]
attribute with an object that conforms to the TreeModel
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' }]
}
]
};
}
node_modules/ng2-tree/styles.css
In Angular 2/4 cli projects, modify .angular-cli.json as below:
"styles": [
"styles.css",
"../node_modules/ng2-tree/styles.css"
],
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
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.
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)"
(nodeExpanded)="handleExpanded($event)"
(nodeCollapsed)="handleCollapsed($event)"
(loadNextLevel)="handleNextLevel($event)">
</tree>
Let's go through every element of this structure one by one.
tree
is the selector for TreeComponent
which is bundled into TreeModule
:
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;
id: string | number;
children?: Array<TreeModel>;
loadChildren?: ChildrenLoadingFunction;
settings?: TreeModelSettings;
}
As you can see - an object that conforms to this interface has a recursive nature, an 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);
}
}
]
};
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.
You can also load children by changing the tree state using ngrx.The tree can emit an appropriate event notifying you to dispatch a new action in order to load the branch's children.
To enable this feature you should set the TreeModel.emitLoadNextLevel
property to true:
const model: TreeModel = {
emitLoadNextLevel : true
}
Now on the first time the node is expanded a LoadNextLevelEvent will be fired (via the loadNextLevel EventEmitter in the tree) containing the node that requested a next level (its children) loading.
In your code make sure you change the tree state and add the children to the model.
In addition the regular NodeExpanded event will be fired.
NOTICE: if both emitLoadNextLevel
and loadChildren
are provided, the tree will ignore the emitLoadNextLevel
and the LoadNextLevelEvent
won't be fired.
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,
'rightMenu': true,
'leftMenu': true,
'cssClasses': {
'expanded': 'fa fa-caret-down fa-lg',
'collapsed': 'fa fa-caret-right fa-lg',
'leaf': 'fa fa-lg',
'empty': 'fa fa-caret-right disabled'
},
'templates': {
'node': '<i class="fa fa-folder-o fa-lg"></i>',
'leaf': '<i class="fa fa-file-o fa-lg"></i>',
'leftMenu': '<i class="fa fa-navicon fa-lg"></i>'
},
'menuItems': [
{ action: NodeMenuItemAction.Custom, name: 'Foo', cssClass: 'fa fa-arrow-right' },
{ action: NodeMenuItemAction.Custom, name: 'Bar', cssClass: 'fa fa-arrow-right' },
{ action: NodeMenuItemAction.Custom, name: 'Baz', cssClass: 'fa fa-arrow-right'}
]
}
},
children: [
{value: 'JavaScript'},
{value: 'CoffeeScript'},
{value: 'Lua'}
]
}
static
- Boolean - 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.isCollapsedOnInit
- Boolean - This option makes a tree to be collapsed on first load (this option cascades to its children).rightMenu
- Boolean - This option allows you to activate (true, by default) or deactivate (false) right menu when clicking with right button of a mouse.leftMenu
- Boolean - This option allows you to activate (true) or deactivate (false, by default) left menu.cssClasses
- Object:
expanded
- String - It specifies a css class (or classes) for an item which represents expanded state of a node. The item is clickable and it transitions the node to the collapsed statecollapsed
- String - It specifies a css class (or classes) for an item which represents collapsed state of a node. The item is clickable and it transitions the node to the expanded stateleaf
- String - It specifies a css class (or classes) for an item which represents a node without an option to expand or collapse - in other words: a leaf node.empty
- String - Node is considered empty when it has no children. Once this condition is satisfied - appropriate css class will be applied to the node.templates
- Object:
node
- String - It specifies a html template which will be included to the left of the node's value.leaf
- String - It specifies a html template which will be included to the left of the leaf's value.leftMenu
- String - It specifies a html template to the right of the node's value. This template becomes clickable and shows a menu on node's click.menuItems
- here you can specify your custom menu items. You should feed an array of NodeMenuItem instances to this setting. Once done - setup a subscription to MenuItemSelectedEvent
s by listening to (menuItemSelected)="onMenuItemSelected($event)"
on the tree.All options that are defined on a parent
are automatically applied to children. If you want you can override them by settings
of the child node.
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
classAlso 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.)
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.
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>{...}}
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>{...}}
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>{...}}
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 and a controller
property, which will give you access to node's controller.
{node: <Tree>{...}}
You can subscribe to NodeRenamedEvent
by attaching listener to (nodeRenamed)
attribute
<tree
[tree]="tree"
(nodeRenamed)="handleRenamed($event)">
</tree>
NodeRenamedEvent
has three properties:
node
contains a node that was renamed ( an instance of Tree
).oldValue
contains a value, that node used to have (it might be string
or RenamableNode
)newValue
contains a new value of the node (it might be string
or RenamableNode
){
node: <Tree>{...},
oldValue: <string|RenamableNode>{...},
newValue: <string|RenamableNode>{...}
}
You can subscribe to NodeExpandedEvent
by attaching listener to (nodeExpanded)
attribute, this event wont fire on initial expansion
<tree
[tree]="tree"
(nodeExpanded)="handleExpanded($event)">
</tree>
NodeExpandedEvent
has a node
property of type Tree
, which contains an expanded node.
{node: <Tree>{...}}
You can subscribe to NodeCollapsedEvent
by attaching listener to (nodeCollapsed)
attribute
<tree
[tree]="tree"
(nodeCollapsed)="handleCollapsed($event)">
</tree>
NodeCollapsedEvent
has a node
property of type Tree
, which contains a collapsed node.
{node: <Tree>{...}}
You can subscribe to LoadNextLevelEvent
by attaching a listener to (loadNextLevel)
attribute.Relevant for loading children via ngrx (or any redux-inspired library).
<tree
[tree]="tree"
(loadNextLevel)="handleNextLevel($event)">
</tree>
LoadNextLevelEvent
has a node
property of the type Tree
, which contains a node for which next level (its children) should be loaded.
{node: <Tree>{...}}
First of all you should know how to get a controller of a particular node. You can get a controller of a node only if you set an id property of a node.
TIP: Ids for nodes created via the context menu or using a TreeController instance get populated automatically unless nodes had ids before there were added to the tree
For example, your tree structure should look like:
public tree: TreeModel = {
value: 'Programming languages by programming paradigm',
id: 1,
children: [
{
value: 'Object-oriented programming',
id: 2,
children: [
{value: 'Java', id: 3},
{value: 'C++', id: 4},
{value: 'C#', id 5},
]
},
{
value: 'Prototype-based programming',
id: 6,
children: [
{value: 'JavaScript', id: 7},
{value: 'CoffeeScript', id: 8},
{value: 'Lua', id: 9},
]
}
]
};
Ids must be unique within a one tree, otherwise, some controllers will be overwritten and you won't be able to acquire them.In order to get a node's controller you need to create an Angular local variable out of tree component via hash binding in the template:
@Component({
template: '<tree [tree]="tree" #treeComponent></tree>'
})
class TheComponent implements AfterViewInit {
tree: TreeModel = {
value: 'Programming languages by programming paradigm',
id: 1,
children: [
{
value: 'Object-oriented programming',
id: 2,
children: [
{value: 'Java', id: 3},
{value: 'C++', id: 4},
{value: 'C#', id 5},
]
},
{
value: 'Prototype-based programming',
id: 6,
children: [
{value: 'JavaScript', id: 7},
{value: 'CoffeeScript', id: 8},
{value: 'Lua', id: 9},
]
}
]
};
@ViewChild('treeComponent') treeComponent;
ngAfterViewInit(): void {
// ... make use of this.treeComponent ...
}
}
then by executing this.treeComponent.getControllerByNodeId(PUT_HERE_YOUR_NODE_ID)
you'll get an instance of a TreeController (another couple steps and the world is yours =) )
Below are more detailed explanations of the TreeController and its usage. Let's go method by method:
const oopNodeController = this.treeComponent.getControllerByNodeId(2);
oopNodeController.select();
This method selects the node and unselects all the other nodes, also it fires a select event.
oopNodeController.isSelected();
This method returns true if the node is selected and false if it isn't.
oopNodeController.collapse();
This method collapses a node if the node is collapsible (for example we cannot collapse a leaf). If the node gets collapsed successfully - a collapse event gets fired.
oopNodeController.isCollapsed();
This method returns true if the node is collapsed and false otherwise.
oopNodeController.expand();
This method expands the node in case it can be expanded. On successful expanding the expand event is fired.
oopNodeController.expandToParent();
This method expands the node even if it is a leaf. Expand event is fired for every expanded parent up to the root.
Important: For this to work - keepNodesInDOM: true
should be set on the appropriate tree.
oopNodeController.isExpanded();
Actually controller makes and returns a clone of tree's underlying model
oopNodeController.toTreeModel();
This method returns true if the node is expanded and false otherwise.
oopNodeController.rename('new value');
This method accepts a string and sets it as a node's new value, this action also fires rename event.
oopNodeController.startRenaming();
After the user entered the new name a rename event will be fired.
oopNodeController.remove();
This method removes the node and its children and fires remove event.
let newNode: TreeModel = {
value: 'Go',
children: []
};
oopNodeController.addChild(newNode);
This method accepts a TreeModel and adds it as a child of the parent or as a sibling (depends on which controller this was called - branch controller or a leaf controller).
oopNodeController.changeNodeId(10);
This method can change a node's id. When the user creates a node from node's menu you will access the new node after it's created and this method will provide a way to change the node's id.
oopNodeController.reloadChildren();
let newChildren: Array<TreeModel> = [
{ value: 'new children 1' },
{ value: 'new children 2' },
{ value: 'new children 3' }
];
oopNodeController.setChildren(newChildren);
This method replaces all existing children of the node with new ones.
If you are using SystemJS, then you need
System.config({
// ...
map: {
// ...
'ng2-tree': 'node_modules/ng2-tree/bundles/ng2-tree.umd.min.js',
// ...
},
// ...
}
parent
. It's not the case anymore. If you need a parent you should get it from node
in event object like node.parent
;node
property of type TreeModel
. Now node
is of type Tree (as well as node.parent
);NodeMovedEvent
now has property previousParent
, which contains tree in which moved node used to be.node_modules/ng2-tree/styles.css
. That allows you to override ng2-tree styles more easily.I am very appreciate for your ideas, proposals and found bugs which you can put in github issues. Thanks in advance!
P.S. If you find it hard going through the documentation, please, let me know which parts of it was difficult to grasp and I will improve them.
tree: 将你要构建树的数据按照TreeModel转化就行了 this._tree = { value: '所有一级分类', id: 0, children: [], settings: this._settings }; //constructor first
与select和tree的结合体。 基本使用 /** 0.支持双向绑定和ngModelChange。 1.nzExpandedKeys:展开的节点keys 2.nzShowSearch:是否显示模糊搜索,默认false 3.nzAllowClear:是否支持clear,默认true 4.nzMultiple:是否支持多选 */ <nz-tree-select style="
const res = new Map(); c.children = c.children.filter((a) => !res.has(a.label) && res.set(a.label, 1))
nz-tree中数据的初始化 1 新建父节点 var nzTreeNode ,并赋值 其中children为[], 2 新建var nzTreeNodeChild 3 通过 nzTreeNode[“children”].push(nzTreeNodeChild) 给父节点的children赋值; nz-tree选中项的高亮显示 主要是通过selected属性来设置的,将其设置为true时为高亮显示
还有一个tree-select组件。 基本使用 /** 1.nzData:绑定数据 2.nzTreeComponent:获取dom节点,可以使用tree的一些方法 3.nzCheckable:是否带有checkbox,默认false。 4.nzShowExpand:是否有折叠按钮,默认true 5.nzBlockNode:节点是否是block(选中的默认颜色占满),默认fals
完整代码如下: import { Component } from '@angular/core'; import { NzFormatEmitEvent } from 'ng-zorro-antd/tree'; import { NzTreeComponent, NzTreeNodeOptions } from 'ng-zorro-antd/tree'; @Component({ sel
Angular 2 Drag-and-Drop Angular 2 Drag-and-Drop without dependencies. Follow me to be notified about new releases. Some of these APIs and Components are not final and are subject to change! Transpilat
ng2-translate 是 Angular 2 的 i18n 库。 简单示例:https://stackblitz.com/github/ngx-translate/example
ng2-bootstrap 是 Angular 2 的扩展指令,实现了对 Bootstrap 框架的集成。 示例代码: // RECOMMENDED (doesn't work with system.js)import { AccordionModule } from 'ng2-bootstrap/accordion';// orimport { AccordionModule } from '
个人开发的博客,前端ng2-fuzhutech-blog采用angualr2 + ng2-Bootstrap实现,后端fuzhutech-blog基于Spring+SpringMVC+Mybatis架构. This project was generated with Angular CLI version 1.0.0. 技术选型 后端 Ioc容器 Spring Web框架 SpringMVC O
This repository is no longer maintained. Angular 2+ wrapper for intl-tel-input Installation Run following command to install ng2-tel-input npm install ng2-tel-input intl-tel-input --save After install
Angular PDFJS viewer with Mozilla's ViewerJS. Supports Angular 2+ �� Thanks a ton to the community - We are talking Downloads in millions now!!! This project is currently maintained by a single develo