This page shows how to get started with Wijmo's TreeView control.
Getting Started
Steps for getting started with Input controls in AngularJS applications:
Add references to AngularJS, Wijmo, and Wijmo's AngularJS directives.
Include the Wijmo directives in the app module: var app = angular.module('app', ['wj']);
Add a controller to provide data and logic.
Add a Wijmo Input control to the page and bind it to your data.
(Optional) Add some CSS to customize the input control's appearance.
The examples below demonstrate all this.
Creating Trees
To create trees, you will normally have to set three properties:
itemsSource defines the array that contains the hierarchical data.
Each item in the array contains information about a node and (optionally)
an array of child nodes.
displayMemberPath defines the name of the property in the items
that contains the text to be displayed in the tree nodes. By default, this
property is set to the string 'header'.
childItemsPath defines the name of the property in the items that
contains the array of child nodes. By default, this property is set to the
string 'items'.
There are also properties for binding node images, checkboxes, and collapsed
state to the itemsSource array.
By default, the TreeView expands the first node of each level when it loads
the tree. You can customize that behavior using the collapsedMemberPath
property to control the collapsed state of each node, or call the
collapseToLevel method after the tree is loaded to collapse all nodes
deeper than the level you want to show.
Once the tree is loaded, you can select, collapse, or expand nodes using the
mouse or the keyboard. You can also use the keyboard to search for nodes.
The TreeView control uses animations to expand and collapse nodes by default.
You can turn this feature off by setting the isAnimated property to
false.
It also collapses sibling nodes automatically when a node is expanded.
You can turn this feature off by setting the autoCollapse property
to false.
By default, the TreeView control expands collapsed nodes when the user
clicks anywhere on the node. You can change this by setting the
expandOnClick property to false, in which case only clicks
on the collapsed/expanded glyph will affect the collapsed state.
/* default trees on this sample */
.wj-treeview {
height: 350px;
font-size: 120%;
margin-bottom: 8px;
background: white;
box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23);
}
Result (live):
Styling and CSS
You can customize the appearance of the TreeView using CSS.
This example changes the collapse/expand icons, uses different
font sizes depending on node level, and adds a vertical bar to
the left of the level one nodes.
Use the checkbox below the TreeView to toggle the custom style
and see the difference.
The simplest and most common use for the TreeView control is navigation.
The TreeView's hierarchical structure and auto-search functionality make
it easy for users to drill-down and find the items they are interested in.
You can use the selectedItemChanged or itemClicked events
for navigation. The difference is that selectedItemChanged occurs
when the user moves the selection with the keyboard, and itemClicked
occurs when the user clicks an item or presses the Enter key.
Accordions are multi-pane panels that keep only one panel expanded
at a time. They are commonly used for navigation.
You can use the TreeView control to implement accordions.
Use CSS to customize the header display and to hide the
collapse/expand glyphs, and make sure the autoCollapse
property is set to true (the default), so non-active panels
are automatically collapsed.
Set the showCheckboxes property to true and the TreeView will
add checkboxes to each node.
When checkboxes are displayed, the TreeView manages their
hierarchy so that when a checkbox is checked or cleared, the new
value is automatically applied to all child nodes, and reflected
on the state of the parent nodes.
When items are checked or unchecked, the checkedItemsChanged
event is raised, and the checkedItems property is updated
with a list of the items that are currently checked.
// disable node
$scope.disableNode= function (treeView) {
var nd = treeView.selectedNode;
if (nd) {
nd.isDisabled = true;
}
}
// enable all nodes
$scope.enableAllNodes = function (treeView) {
for (var nd = treeView.getFirstNode(); nd; nd = nd.next()) {
nd.isDisabled = false;
}
}
Result (live):
Custom Node Content
You can customize the content of the TreeView nodes using the formatItem
event. The event handler parameters include the element that represents the node
and the data item being rendered.
The example below uses the formatItem event to add a "new" badge to the
right of new items on the tree.
// enable all nodes
$scope.formatItem = function (s, e) {
if (e.dataItem.newItem) {
e.element.innerHTML +=
' <img style="margin-left:6px;transform:rotate(-30deg)" src="resources/new.png"/>';
}
}
Result (live):
Lazy Loading
Lazy loading is useful when you are dealing with large hierarchical data sources
and would like to avoid the delays involved in loading the entire data set at once.
The TreeView control makes lazy-loading super easy. Only two steps are required:
Set the items property in the parent node data item to an empty array.
Set the TreeView's lazyLoadFunction property to a function to be called
when the user expands the node. This function takes two parameters: the parent node
and a callback function to be invoked when the data becomes available.
The tree in example below starts with three lazy-loaded nodes.
When you expand them, the lazyLoadFunction is invoked. The function
uses a setTimeout to simulate an http delay and returns data for three child nodes,
one of which is also a lazy-loaded node.
$scope.lazyItems = [ // start with three lazy-loaded nodes
{ header: 'Lazy Node 1', items: [] },
{ header: 'Lazy Node 2', items: [] },
{ header: 'Lazy Node 3', items: [] }
];
$scope.lazyLoadFunction =function (node, callback) {
setTimeout(function () { // simulate http delay
var result = [ // simulate result
{ header: 'Another lazy node...', items: [] },
{ header: 'A non-lazy node without children' },
{ header: 'A non-lazy node with child nodes', items: [
{ header: 'hello' },
{ header: 'world' }
]}
];
callback(result); // return result to control
}, 2500); // 2.5sec http delay
}
}
Result (live):
Lazy Loading and OData
This example shows how you can use the TreeView control to display
hierarchical data from OData sources.
The sample starts by loading the Northwind employees table. When the
data is loaded, the code adds an "Orders" empty array to each employee.
The lazyLoadFunction is used to load the orders when an employee
node is expanded.
The orders table also adds an "Order_Details" empty array to each
order. The lazyLoadFunction is used to load the order details
when an order node is expanded.
Set the allowDragging property to true to allow users to drag nodes to new
positions within the TreeView.
When dragging is allowed, users may drag any node to any position within the tree.
You can customize this behavior by handling the TreeView drag/drop events:
dragStart: Occurs when a drag/drop operation is about to start. You
may examine the node about to be dragged and cancel the operation by
setting the event's cancel parameter to true.
dragOver: Occurs while the user drags the node over other nodes on
the tree. You may examine the current target node and drop position and
prevent the drop or modify its location setting the event's cancel
and position parameters.
drop: Occurs when the user drops the node into its new location.
You may examine the current target node and drop position and
prevent the drop or modify its location setting the event's cancel
and position parameters.
dragEnd: Occurs after the drag/drop operation is finished, even if
it was canceled and the source node was not moved.
$scope.allowDraggingParentNodes = true;
$scope.allowDroppingIntoEmpty = true;
// use dragStart event to honor the allowDraggingParentNodes setting
// by setting the 'cancel' event parameter to true
$scope.dragStart = function (s, e) {
if (e && e.node.hasChildren) {
if (!$scope.allowDraggingParentNodes) {
e.cancel = true; // prevent dragging parent nodes
} else {
e.node.isCollapsed = true; // collapse parent nodes when dragging
}
}
}
// use dragOver event to honor the allowDroppingIntoEmpty setting
// by changing the 'position' event parameter to 'Before'
$scope.dragOver = function (s, e) {
if (!$scope.allowDroppingIntoEmpty &&
!e.dropTarget.hasChildren &&
e.position == wijmo.input.DropPosition.Into) {
e.position = wijmo.input.DropPosition.Before;
}
}
Result (live):
Drag and Drop Between Trees
Setting the allowDrag property to true allows users to drag and drop nodes
within the same TreeView.
To allow dragging and dropping nodes between different TreeView controls, you must
handle the dragOver event and set the cancel parameter to true if
the move is not valid, or to false if it is valid.
In the example below, users can drag nodes within and between the two trees:
The TreeView control provides editing support. Set the isReadOnly
property to false and users will be able to edit the content of the nodes
by pressing the F2 key.
Edits made to node contents are automatically applied to the items in
the itemsSource array using the properties specified by the
displayMemberPath property.
You may customize the editing behavior using the following events:
nodeEditStarting, nodeEditStarted,
nodeEditEnding, and nodeEditEnded.
In the example below, we enable editing only for nodes that contain no
children. To edit, select a node and press F2:
$scope.nodeEditStarting = function (s, e) {
if (e.node.hasChildren) {
e.cancel = true;
}
}
Result (live):
RTL support
Some languages render content from the right to the left of the page
(Arabic and Hebrew are typical examples) .
HTML accommodates this with the 'dir' attribute. Setting 'dir' to 'rtl'
on any element causes the element's content to flow from right to left.
The TreeView supports this automatically. If the element hosting the tree
has the 'dir' attribute set to 'rtl', the tree will render with nodes
extending from right to left. You don't have to set any properties on the
control.
Note that the 'dir' attribute value is inherited, so if you set it on the
body tag for example, the entire page will be rendered from right to left,
including the tree.
Note also that CSS has a 'direction' attribute that performs the same
function as the 'dir' element attribute. The 'dir' attribute is generally
considered more appropriate for several reasons, including the fact that
it can be used in CSS rules.