Angular UI Tree
======================
[![Build Status](https://travis-ci.org/angular-ui-tree/angular-ui-tree.svg?branch=master)](https://travis-ci.org/angular-ui-tree/angular-ui-tree)
Angular UI Tree is an AngularJS UI component that can sort nested lists, provides drag & drop support and doesn't depend on jQuery. If you are a user who uses `angular-nestedSortable`, this is [How to migrate From v1.x to v2.0](https://github.com/JimLiu/angular-ui-tree/wiki/Migrate-From-v1.x-to-v2.0).
## Features
- Uses the native AngularJS scope for data binding
- Sorted and move items through the entire tree
- Prevent elements from accepting child nodes
## Supported browsers
The Angular UI Tree is tested with the following browsers:
- Chrome (stable)
- Firefox
- IE 8, 9 and 10
For IE8 support, make sure you do the following:
- include an [ES5 shim](https://github.com/es-shims/es5-shim)
- make your [AngularJS application compatible with Internet Explorer](http://docs.angularjs.org/guide/ie)
- use [jQuery 1.x](http://jquery.com/browser-support/)
## Demo
Watch the Tree component in action on the [demo page](http://jimliu.github.io/angular-ui-tree/).
## Requirements
- Angularjs
## Usage
### Download
- Using [bower](http://bower.io/) to install it. `bower install angular-ui-tree`
- [Download](https://github.com/JimLiu/angular-ui-tree/archive/master.zip) from github.
### Load CSS
Load the css file: `angular-ui-tree.min.css` in your application:
```html
```
### Load Script
Load the script file: `angular-ui-tree.js` or `angular-ui-tree.min.js` in your application:
```html
```
### Code
Add the sortable module as a dependency to your application module:
```js
var myAppModule = angular.module('MyApp', ['ui.tree'])
```
Injecting `ui.tree`, `ui-tree-nodes`, `ui-tree-node`, `ui-tree-handle` to your html.
#### HTML View or Templates
```html
{{item.title}}
{{subItem.title}}
```
**Developing Notes:**
- Adding `ui-tree` to your root element of the tree.
- Adding `ui-tree-nodes` to the elements which contain the nodes. `ng-model` is required, and it should be an array, so that the directive knows which model to bind and update.
- Adding `ui-tree-node` to your node element, it always follows the `ng-repeat` attribute.
- Adding `ui-tree-handle` to the element used to drag the object.
- All `ui-tree`, `ui-tree-nodes`, `ng-model`, `ui-tree-node` are necessary. And they can be nested.
- If you don't add a `ui-tree-handle` for a node, the entire node can be dragged.
#### Unlimited nesting HTML View or Templates Example
```html
```
## Structure of angular-ui-tree
ui-tree --> Root of tree
ui-tree-nodes --> Container of nodes
ui-tree-node --> One of the node of a tree
ui-tree-handle --> Handle
ui-tree-nodes --> Container of child-nodes
ui-tree-node --> Child node
ui-tree-handle --> Handle
ui-tree-node --> Child node
ui-tree-node --> Another node
ui-tree-handle --> Handle
## Migrate From v1.x to v2.0
[Migrate From v1.x to v2.0](https://github.com/JimLiu/angular-ui-tree/wiki/Migrate-From-v1.x-to-v2.0)
## API
### ui-tree
`ui-tree` is the root scope for a tree
#### Attributes
##### data-drop-enabled
Turn on the ability to prevent dropping of nodes into this tree.
- `false` (default): turn off
- `true`: turn on no drop
##### data-clone-enabled
Turn on cloning of nodes. This will clone the source node to the destination when dragging between 2 trees.
- `false` (default): turn off clone
- `true`: turn on clone
##### data-drag-enabled
Turn on dragging and dropping of nodes.
- `true` (default): allow drag and drop
- `false`: turn off drag and drop
##### data-max-depth
Number of levels a nodes can be nested (default 0). 0 means no limit.
**Note**
If you write your own [$callbacks.accept](#accept) method, you have to check `data-max-depth` by yourself.
##### data-drag-delay
Number of milliseconds a click must be held to start a drag. (default 0)
##### data-empty-placeholder-enabled
If a tree is empty, there will be an empty placeholder which is used to drop node from other trees by default.
- `true` (default): display an empty placeholder if the tree is empty
- `false`: do not display an empty placeholder
##### Example
- turn on/off drag and drop.
- Limit depth to 5
- 500 milliseconds delay
```html
```
#### Methods of scope
##### collapseAll()
Collapse all it's child nodes.
##### expandAll()
Expand all it's child nodes.
##### $callbacks (type: Object)
`$callbacks` is a very important property for `angular-ui-tree`. When some special events trigger, the functions in `$callbacks` are called. The callbacks can be passed through the directive.
Example:
```js
myAppModule.controller('MyController', function($scope) {
$scope.treeOptions = {
accept: function(sourceNodeScope, destNodesScope, destIndex) {
return true;
},
};
});
```
```html
{{node.title}}
```
#### Methods in $callbacks
##### accept(sourceNodeScope, destNodesScope, destIndex)
Check if the current dragging node can be dropped in the `ui-tree-nodes`.
**Parameters:**
- `sourceNodeScope`: The scope of source node which is dragging.
- `destNodesScope`: The scope of `ui-tree-nodes` which you want to drop in.
- `destIndex`: The position you want to drop in.
**Return**
If the nodes accept the current dragging node.
- `true` Allow it to drop.
- `false` Not allow.
##### beforeDrag(sourceNodeScope)
Check if the current selected node can be dragged.
**Parameters:**
- `sourceNodeScope`: The scope of source node which is selected.
**Return**
If current node is draggable.
- `true` Allow it to drag.
- `false` Not allow.
##### dropped(event)
If a node moves it's position after dropped, the `nodeDropped` callback will be called.
**Parameters:**
- `event`: Event arguments, it's an object.
* `source`: Source object
+ `nodeScope`: The scope of source node which was dragged.
+ `nodesScope`: The scope of the parent nodes of source node when it began to drag.
+ `index`: The position when it began to drag.
* `dest`: Destination object
+ `nodesScope`: The scope of `ui-tree-nodes` which you just dropped in.
+ `index`: The position you dropped in.
* `elements`: The dragging relative elements.
+ `placeholder`: The placeholder element.
+ `dragging`: The dragging element.
* `pos`: Position object.
##### dragStart(event)
The `dragStart` function is called when the user starts to drag the node.
**Parameters:**
Same as [Parameters](#eventParam) of dropped.
##### dragMove(event)
The `dragMove` function is called when the user moves the node.
**Parameters:**
Same as [Parameters](#eventParam) of dropped.
##### dragStop(event)
The `dragStop` function is called when the user stop dragging the node.
**Parameters:**
Same as [Parameters](#eventParam) of dropped.
##### beforeDrop(event)
The `beforeDrop` function is called before the dragging node is dropped.
**Parameters:**
Same as [Parameters](#eventParam) of dropped.
### ui-tree-nodes
`ui-tree-nodes` is the container of nodes. Every `ui-tree-node` should have a `ui-tree-nodes` as it's container, a `ui-tree-nodes` can have multiple child nodes.
#### Attributes
##### data-nodrop-enabled
Turn off drop of nodes.
##### data-max-depth
Number of levels a nodes can be nested (default 0). 0 means no limit. It can override the `data-max-depth` in `ui-tree`.
**Note**
If you write your own [$callbacks.accept](#accept) method, you have to check `data-nodrop-enabled` and `data-max-depth` by yourself.
Example: turn off drop.
```html
{{node.title}}
```
#### Properties of scope
##### $element (type: AngularElement)
The html element which bind with the `ui-tree-nodes` scope.
##### $modelValue (type: Object)
The data which bind with the scope.
##### $nodes (type: Array)
All it's child nodes. The type of child node is scope of `ui-tree-node`.
##### $nodeScope (type: Scope of ui-tree-node)
The scope of node which current `ui-tree-nodes` belongs to.
For example:
ui-tree-nodes --> nodes 1
ui-tree-node --> node 1.1
ui-tree-nodes --> nodes 1.1
ui-tree-node --> node 1.1.1
ui-tree-node --> node 1.1.2
ui-tree-node --> node 1.2
The property `$nodeScope of` `nodes 1.1` is `node 1.1`. The property `$nodes` of `nodes 1.1` is [`node 1.1.1`, `node 1.1.2`]
##### maxDepth
Number of levels a node can be nested. It bases on the attribute [data-max-depth](#nodes_attrs_maxDepth).
##### nodropEnabled
Turn off drop on nodes. It bases on the attribute [data-nodrop-enabled](#nodes_attrs_nodrop).
#### Methods of scope
##### depth()
Get the depth.
##### outOfDepth(sourceNode)
Check if depth limit has reached
##### isParent(nodeScope)
Check if the nodes is the parent of the target node.
**Parameters:**
- `nodeScope`: The target node which is used to check with the current nodes.
### ui-tree-node
A node of a tree. Every `ui-tree-node` should have a `ui-tree-nodes` as it's container.
#### Attributes
##### data-nodrag
Turn off drag of node.
Example: turn off drag.
```html
{{node.title}}
```
##### data-collapsed
Collapse the node.
#### Properties of scope
##### $element (type: AngularElement)
The html element which bind with the `ui-tree-nodes` scope.
##### $modelValue (type: Object)
The data which bind with the scope.
##### collapsed (type: Bool)
If the node is collapsed
- `true`: Current node is collapsed;
- `false`: Current node is expanded.
##### $parentNodeScope (type: Scope of ui-tree-node)
The scope of parent node.
##### $childNodesScope (type: Scope of ui-tree-nodes)
The scope of it's `ui-tree-nodes`.
##### $parentNodesScope (type: Scope of ui-tree-nodes)
The scope of it's parent `ui-tree-nodes`.
For example:
ui-tree-nodes --> nodes 1
ui-tree-node --> node 1.1
ui-tree-nodes --> nodes 1.1
ui-tree-node --> node 1.1.1
ui-tree-node --> node 1.1.2
ui-tree-node --> node 1.2
- `node 1.1.1`.`$parentNodeScope` is `node 1.1`.
- `node 1.1`.`$childNodesScope` is `nodes 1.1`.
- `node 1.1`.`$parentNodesScope` is `nodes 1`.
#### Methods of scope
##### collapse()
Collapse current node.
##### expand()
Expand current node.
##### toggle()
Toggle current node.
##### remove()
Remove current node.
##### depth()
Get the depth of the node.
##### maxSubDepth()
Get the max depth of all the child nodes. If there is no child nodes, return 0.
##### isSibling(targetNodeScope)
Check if the current node is sibling with the target node.
**Parameters:**
- `targetNodeScope`: The target node which is used to check with the current node.
##### isChild(targetNodeScope)
Check if the current node is a child of the target node.
**Parameters:**
- `targetNodeScope`: The target node which is used to check with the current node.
### ui-tree-handle
Use the `ui-tree-handle` to specify an element used to drag the object. If you don't add a `ui-tree-handle` for a node, the entire node can be dragged.
## NgModules Link
[Give us a like on ngmodules](http://ngmodules.org/modules/angular-ui-tree)
## Development environment setup
#### Prerequisites
* [Node Package Manager](https://npmjs.org/) (NPM)
* [Git](http://git-scm.com/)
#### Dependencies
* [Gulp](http://gulpjs.com/) (task automation)
* [Bower](http://bower.io/) (package management)
#### Installation
Run the commands below in the project root directory.
#####1. Install Gulp and Bower
$ sudo npm install -g gulp bower
#####2. Install project dependencies
$ npm install
$ bower install
## Useful commands
####Running a Local Development Web Server
To debug code and run end-to-end tests, it is often useful to have a local HTTP server. For this purpose, we have made available a local web server based on Node.js.
To start the web server, run:
$ gulp serve
To access the local server, enter the following URL into your web browser:
http://localhost:9000
By default, it serves the contents of the `examples` directory.
####Building angular-ui-tree
To build angular-ui-tree, you use the following command.
$ gulp build
This will generate non-minified and minified JavaScript files in the `dist` directory.
####Run tests
You can run the unit test using a separate task.
$ gulp test