a suite of UI Components for development of web apps
If you have any questions, don't hesitate to contact us at support@lidorsystems.com
Advanced User Interface Controls and Components
Created: 23 August 2016
Updated: 24 March 2017
IntegralUI TreeView is a native Angular 2 component that displays tree hierarchy of items that can be reordered using advanced drag drop operations. You can load data on demand during run-time from local or remote data sources, and add custom HTML content in each tree item. In following sections, you can find details about various features available in the TreeView component.
If you have any questions, don't hesitate to contact us at support@lidorsystems.com
Above demonstration shows a simple tree hierarchy, each item has an icon and an editable label. When item is hovered, a command button will appear on right side, which when clicked will open a text editor, where you can change the item label.
You can reorder items by click and drag over specific item. A dragging window will appear, stating the target item and position at which item can be dropped. During drag drop operations, you can also create a copy of an item by holding the SHIFT key. The dragging window will change its icon, showing a + sign next to position marker.
Furthermore, expanding and collapsing of items is animated using built-in animation.
In order to use the TreeView component in your app, you need to do the following:
Because tree hierarchy can contain items in many levels, instead of setting a tree in HTML, you can just set the template by which each item is created:
//
// main.ts file
//
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);
//
// app.module.ts file
//
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { IntegralUIModule } from 'integralui/integralui.module';
@NgModule({
imports: [ BrowserModule, IntegralUIModule ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
//
// app.component.ts file
//
import { Component, ViewEncapsulation } from '@angular/core';
@Component({
selector: 'iui-app',
templateUrl: 'app.template.html',
styleUrls: ['treeview-overview.css'],
encapsulation: ViewEncapsulation.None
})
export class AppComponent {
// An Array object that holds all item objects shown in TreeView
// It is set as a list of any custom objects, you can use any custom fields and data bind them with TreeView using its properties
public items: Array<any>;
// Get a reference of application view
@ViewChild('application', {read: ViewContainerRef}) applicationRef: ViewContainerRef;
// Editor settings
private isEditActive: boolean = false;
private editItem = null;
private originalText: string = '';
private editorFocused: boolean = false;
private hoverItem = null;
// Initialize items in component constructor
constructor(){
this.items = [
{
id: 1,
text: "Favorites",
icon: "computer-icons favorites",
items: [
{ id: 11, pid: 1, text: "Desktop", icon: "computer-icons empty-doc" },
{ id: 12, pid: 1, text: "Downloads", icon: "computer-icons downloads" }
]
},
{
id: 2,
text: "Libraries",
icon: "computer-icons folder",
items: [
{
id: 21,
pid: 2,
text: "Documents",
icon: "computer-icons documents",
expanded: false,
items: [
{ id: 211, pid: 21, text: "My Documents", icon: "computer-icons empty-doc" },
{ id: 212, pid: 21, text: "Public Documents", icon: "computer-icons empty-doc" }
]
},
{ id: 22, pid: 2, text: "Music", icon: "computer-icons music" },
{ id: 23, pid: 2, text: "Pictures", icon: "computer-icons pictures" },
{ id: 24, pid: 2, text: "Videos", icon: "computer-icons videos" }
]
},
{
id: 3,
text: "Computer",
icon: "computer-icons pc",
expanded: false,
items: [
{ id: 31, pid: 3, text: "Local Disk (C:)", icon: "computer-icons disk" },
{ id: 32, pid: 3, text: "Storage (D:)", icon: "computer-icons disk" }
]
},
{ id: 4, text: "Network", icon: "computer-icons network" },
{ id: 5, text: "Recycle Bin", icon: "computer-icons recycle" }
];
}
showEditor(item){
this.originalText = item.text;
this.isEditActive = true;
this.editItem = item;
this.editorFocused = true;
}
closeEditor(){
this.editItem = null;
this.originalText = '';
this.editorFocused = false;
}
editorKeyDown(e){
if (this.editItem){
switch (e.keyCode){
case 13: // ENTER
this.closeEditor();
break;
case 27: // ESCAPE
this.editItem.text = this.originalText;
this.closeEditor();
break;
}
}
}
editorLostFocus(){
if (this.editItem)
this.editItem.text = this.originalText;
this.closeEditor();
}
}
bootstrap(AppComponent);
//
// app.template.html file
//
<div #application>
<iui-treeview [items]="items" [appRef]="applicationRef" #treeview>
<template let-item>
<div (mouseenter)="hoverItem=item" (mouseleave)="hoverItem=null">
<span [ngClass]="item.icon"></span>
<span *ngIf="item!=editItem">{{item.text}}</span>
<input *ngIf="item==editItem" type="text" [(ngModel)]="item.text" (keydown)="editorKeyDown($event)" (blur)="editorLostFocus()" [iuiFocus]="editorFocused" onFocus="this.setSelectionRange(0, this.value.length)" />
<div class="toolbar" *ngIf="item==hoverItem">
<span class="item-button item-button-edit" (click)="showEditor(item)"></span>
</div>
</div>
</template>
</iui-treeview>
</div>
/*
treeview-overview.css file
*/
.iui-treeview
{
width: 350px;
height: 350px;
}
.computer-icons
{
background-image: url(../../resources/computer.png);
background-repeat: no-repeat;
display: inline-block;
overflow: hidden;
padding: 0 !important;
margin: 0 2px 0 0;
width: 24px;
height: 24px;
vertical-align: middle;
}
.empty
{
background-position: 0px 0px;
}
.folder
{
background-position: -24px 0px;
}
.downloads
{
background-position: -48px 0px;
}
.favorites
{
background-position: -72px 0px;
}
.documents
{
background-position: -96px 0px;
}
.pc
{
background-position: -120px 0px;
}
.videos
{
background-position: -144px 0px;
}
.music
{
background-position: -168px 0p;
}
.network
{
background-position: -192px 0px;
}
.recycle
{
background-position: -216px 0px;
}
.pictures
{
background-position: -240px 0px;
}
.empty-doc
{
background-position: -264px 0px;
}
.disk
{
background-position: -288px 0px;
}
.toolbar
{
display: inline-block;
position: absolute;
right: 0;
top: 7px;
padding-left: 5px;
}
.item-button
{
background-image: url(../../../resources/icons.png);
background-repeat: no-repeat;
display: inline-block;
float: right;
height: 16px;
margin: 3px 4px 0 4px;
opacity: 0.5;
overflow: hidden;
padding: 0;
width: 16px;
}
.item-button:hover
{
opacity: 1;
}
.item-button-edit
{
background-position: -128px -81px;
}
Note If you want to show some item with different content then other items, you can use the directive and set condition by which a different content will appear.
In this example, each item has an icon, label, editor (represented by input element) and a command button on the right side. The editor is only visible when the button is clicked. After editing is completed or cancelled, the editor will disappear.
<template let-item>
<div (mouseenter)="hoverItem=item" (mouseleave)="hoverItem=null">
<span [ngClass]="item.icon"></span>
<span *ngIf="item!=editItem">{{item.text}}</span>
<input *ngIf="item==editItem" type="text" [(ngModel)]="item.text" (keydown)="editorKeyDown($event)" (blur)="editorLostFocus()" [iuiFocus]="editorFocused" onFocus="this.setSelectionRange(0, this.value.length)" />
<div class="toolbar" *ngIf="item==hoverItem">
<span class="item-button item-button-edit" (click)="showEditor(item)"></span>
</div>
</div>
</template>
When you have a template ready, you need to link the data source with the TreeView using the items property. The data source can be any array in flat or tree format.
All properties of the TreeView component can be set using a separate attribute that is linked to an object in your application scope or to a specified value.
Here is a list of available properties:
To avoid using plain javascript manipulation of the DOM and because of the way Angular 2 is structured, in order to show a tooltip, context menu or any other popup window, a reference to the root application component is required. You can provide a value to appRef property by simply setting a variable to the root component, and then access it by calling the ViewChild with specified variable name.
// Get a reference of application view
@ViewChild('application', {read: ViewContainerRef}) applicationRef: ViewContainerRef;
<div #application>
<iui-treeview [items]="items" [appRef]="applicationRef">
</iui-treeview>
</div>
If you want to have a specified item selected initially, you can set the selectedItem property to point to the item object in your data source. You can also set whether an item will appear as collapsed initially, by specifying the expanded field value to false. By default all items are expanded.
When you have a custom data source which may differ from internal data settings of the tree view, you can use data binding which will match the names of data fields in your data source with those used by the tree view.
By specifying the items property to point to your data object, along with dataFields property that holds an object that maps the names of fields in the data object, you can populate the TreeView using any kind of custom data source.
This feature is also usable when you need to load data on demand in the TreeView, from a remote data source.
Related: Load Data on Demand in TreeView for Angular 2
When interacting with the TreeView component, depending on the action, a corresponding event is fired. For example adding an item will fire itemAdding and itemAdded events, expanding it will fire the beforeExpand and afterExpand events, selecting it will fire beforeSelect, afterSelect and selectionChanged events, etc.
Here is a list of available events:
By handling these events in your code, you can add custom actions that may alter the default behavior of the TreeView component. For example, by handling the dragOver event, you can exclude a specified item as a target during drag drop operation, by setting a condition.
In some cases, you may need to add new items or remove existing items in the TreeView during run-time. For this purpose, there are built-in methods available that allow you to change the structure of the TreeView:
//
// app.component.ts file
//
export class AppComponent {
// An Array object that holds all item objects shown in TreeView
private data: Array
// Get a reference to the TreeView component using a variable set in HTML
@ViewChild('treeview') treeview: IntegralUITreeView;
// Initialize items in component constructor
constructor(){
this.data = [];
}
// Adds a new item to the end of the TreeView
addItem(){
this.treeview.addItem({ text: "Item " + (this.data.length+1).toString() });
}
// Fired whenever a new item is added to the TreeView
itemAddedEvent(e){
if (e.item)
console.log("itemAdded: " + e.item.text);
}
}
bootstrap(AppComponent);
//
// app.template.html file
//
<iui-treeview [items]="data" (itemAdded)="itemAddedEvent($event)" #treeview>
<template let-item>
{{item.text}}
</template>
</iui-treeview>
In above code, we are adding a new item with some items using the addItem method. To access this method, at first we need to get a reference to the TreeView component. In HTML we are adding the #treeview variable, which is used to locate the TreeView within your application component.
Related: Add Item Dynamically in Angular TreeView
After we have a reference to the TreeView component, we can get access to all public methods available:
TreeView component comes with advanced drag drop that allows you to reorder items in tree hierarchy by simply dragging one or multiple items from one place to another within the same or other tree views.
Related: Drag Drop Items Between Two TreeViews in Angular
During this process, events are fired that can help you to add custom actions that may alter the default built-in drag drop functionality. In each event you can set up custom conditions that can prevent or allow drag drop in special cases, depending on your application requirements.
Whenever an item is dragged, a draggin window will appear showing the target item and position at which item can be dropped. There are four possible positions:
By default, during drag and drop items are moved from their original position to a new one. In some cases, instead of moving you may need to create a copy of dragged items. Copy operation is already built-in, you only need to press and hold the SHIFT key, when item is dropped. The dragging window will change its icon showing a + sign. This states that copy of dragged item will drop at specified position.
Each part of IntegralUI TreeView component is fully customizable. There are different CSS classes for each component part. Although changing the attributes of built-in classes is possible, you can completely override them using the controlStyle property.
Related: How to Add CheckBox to Items in Angular TreeView
The controlStyle property accepts an object that holds all or partial list of CSS class names that will override the default CSS class names. For each component part, a different CSS class governs its appearance. This allows you to specify a set of different CSS classes for each component part and alter the appearance of the TreeView in whole. In this way, you can make it more suitable for your application requirements.
IntegralUI TreeView component allows you to display items in a tree hierarchy and reorder them dynamically using advanced drag drop operations. You can populate the TreeView using custom data source, locally or remotely.
By default, each item contains an icon and a label, and when using templates you can add any custom HTML elements or Angular 2 components. With use of ngIf directive, you can have different items with different content.
The TreeView component is part of IntegralUI Web.