An easy way to integrate a tree widget within your Angular projects
- Summary
- Quick warning
- Getting Started
- Usage
- Features
- Using mapper
- Customizing context menu
- API Documentation
- Todo List
- Things ngx-bootstrap-treeview uses
Hi guys, this plugin is still under development and still lacks some features.
The name might be quite confusing but at the moment, there is not any ngx-bootstrap component involved in this plugin. At first I thought I'd need it, then realised I could do everything, at least until now, without using it and I'll try to keep everything going this way.
PS: I think this readme is quite complete. If you find anything missing, don't hesitate to open an issue, I wrote a mnay things over a short period of time, it's highly probable that I forgot to mention something here 😅.
npm install ngx-bootstrap-treeview
Or, if you're using an older version of npm:
npm install ngx-bootstrap-treeview --save
In your app.module.ts
// Import module in your file
import { NgxBootstrapTreeviewModule } from 'ngx-bootstrap-treeview';
@NgModule({
// And then you add it to your array of imports
imports: [NgxBootstrapTreeviewModule]
})
Now in your HTML files, you can use the <ngx-bootstrap-treeview>
tag.
The purpose of this part is to just show some code that you can copy and use straight out of the clipboard. For further documentation refer to the API Documentation part.
<ngx-bootstrap-treeview [isOpened]="true" (leafClicked)="defaultStyleLeafClickedEventHandler($event)" [tree]="tree">
</ngx-bootstrap-treeview>
<ngx-bootstrap-treeview
[isOpened]="true"
(leafClicked)="lightStyleLeafClickedEventHandler($event)"
[tree]="tree"
[disableLeafSelection]="false"
[selectedLeafIcon]="faCheckSquare"
[unselectedLeafIcon]="faSquare"
[openedFolderIcon]="faFolderOpen"
[closedFolderIcon]="faFolder"
[anyChildrenSelectedIcon]="faMinus"
[allChildrenSelectedIcon]="faCheck"
>
</ngx-bootstrap-treeview>
For this section, we'll consider having a Tree[] with the following value:
const roots = [
{
label: 'Langages de programmation',
value: 1,
children: [
{
label: 'C++',
value: 11
},
{
label: 'Angular',
value: 12
},
{
label: 'C#',
value: 13,
children: [
{
label: 'LinQ',
value: 131
},
{
label: 'UWP',
value: 132
},
{
label: 'Sharepoint',
value: 133
},
{
label: 'WPF',
value: 134
}
]
},
{
label: 'Java',
value: 14,
children: [
{
label: 'J2E',
value: 141
},
{
label: 'Spring Framework',
value: 142
},
{
label: 'Vanilla Java',
value: 143
},
{
label: 'Android',
value: 144
}
]
},
{
label: 'Empty folder test',
value: 15,
children: []
}
]
}, {
value: 1111,
label: 'Customers',
children: [
{
label: 'Norton',
value: 156
},
{
label: 'Symantec',
value: 116
},
{
label: 'Some company',
value: 126
},
{
label: 'Zokelion',
value: 196
}
]
}
]
The next paragraphs will just show some HTML snippets that rely on these datas. We'll see later how to use custom objects to build our tree
<!-- Here, roots[0] is a Tree since roots is a Tree[] -->
<ngx-bootstrap-treeview
[tree]="roots[0]"
[mapper]="mapper"
[isOpened]="true"
>
</ngx-bootstrap-treeview>
<ngx-bootstrap-treeview
[trees]="roots"
[mapper]="mapper"
[isOpened]="true"
>
</ngx-bootstrap-treeview>
All icons can be customized, as long as you have access to them in your FontAwesome library. As an example, here, we're using FontAwesome light style. First, let's take an eye to what our TS should look like:
// Import the every IconDefinition you'll want to use
import { faFolder, faFolderOpen, faSquare, faCheckSquare, faCheck, faMinus } from '@fortawesome/pro-light-svg-icons';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
// Register them into your component
public faFolder = faFolder;
public faFolderOpen = faFolderOpen;
public faSquare = faSquare;
public faCheckSquare = faCheckSquare;
public faMinus = faMinus;
public faCheck = faCheck;
}
And then, back to some HTML:
<!-- [propertyYouWantToChangeIcon]="nameInComponent" -->
<ngx-bootstrap-treeview
[isOpened]="true"
[trees]="trees"
[disableLeafSelection]="false"
[selectedLeafIcon]="faCheckSquare"
[unselectedLeafIcon]="faSquare"
[openedFolderIcon]="faFolderOpen"
[closedFolderIcon]="faFolder"
[anyChildrenSelectedIcon]="faMinus"
[allChildrenSelectedIcon]="faCheck"
>
</ngx-bootstrap-treeview>
The mapper takes two maps as a params as well as 2 types. For our example, we'll use these 2 classes to generate our treeview:
class Skill {
public id: number;
public label: string;
public categoryId: number;
}
class Category {
public id: number;
public name: string;
public children: Category[];
public skills: Skill[];
}
Some properties differ from our Tree and Leaf models and we don't need to have the categoryId inside our leaves. A Category stands for a branch and a Skill stands for a Leaf.
If we want to get a tree from such data, we must first re-organize it. That's what the mapper stands for.
As explained above, a mapper takes two types as arguments. First one is the type that will be converted in branch (Tree object), second one is the type that will be converted in leaves. Here, our declaration would look like so:
const mapper: NgxBootsrapTreeviewMapper<Category, Skill>;
Note that it's just a declaration. To instanciate it, we'll need to indicate how our data will be mapped. So let's dive a bit further into the maps.
We have two types of map: TreeMap and LeafMap which are respectively used for mapping trees and leaves. TreeMap has the exact same properties as Tree and LeafMap has the exact same properties as Leaf except that for the maps, all of the properties are of type string because they must contain the name of the key, in the source objects, that will be converted to the given property.
Maps for a treeview that displays skills by categories would look like this:
const treeMap = {
children: 'children',
leavesKey: 'skills',
value: 'id',
label: 'name'
};
const leafMap = {
value: 'id',
label: 'label'
};
So now that we have all of the keys, let's wrap everything we have to get a working mapper:
const mapper = new NgxBootsrapTreeviewMapper<Category, Skill>(treeMap, leafMap);
And then we just give it to our treeview within the HTML
<ngx-bootstrap-treeview
[items]="skillsByCategories"
[mapper]="mapper"
[isOpened]="true"
>
</ngx-bootstrap-treeview>
Version 1.1 introduced a feature that allow user to have a custom context menu when right clicking the tree. This is done by giving an NgxBootstrapTreeviewContextMenus object as an @Input() to the treeview Every interface you may need can be directly imported from ngx-bootstrap-treeview For now, this feature does not support nested menus.
Here is a list of all the @Input():
Name | Type | default value | Description |
---|---|---|---|
tree | Tree | undefined |
Used as datasource for singleroot trees. Equivalent to giving trees with only one item |
trees | Tree[] | undefined |
Used when giving an array of Tree as the datasource |
mapper | NgxBootstrapTreeviewMapper | undefined |
This is mandatory when providing the items or item parameter. It is used when building the treeview. Further documentation below. |
item | Object | undefined |
The object you want to display in the tree. Equivalent to giving items with only one entry. |
items | Object[] | undefined |
List of objects you want to display in the treeview. The tree will use the mapper and iterate over this to build the view. |
isOpened | boolean | false |
If true, first level tree(s) is/are opened by default |
isAnimationDisabled | boolean | false |
Allows the user to disable any animation on branches folding/unfolding |
disableLeafSelection | boolean | false |
Only branches can be selected |
openedFolderIcon | IconDefinition | faFolderOpen |
Icon used to represent an opened branch |
closedFolderIcon | IconDefinition | faFolder |
Icon used to represent a closed branch |
unselectedLeafIcon | IconDefinition | faSquare |
Icon used on not selected leaves |
selectedLeafIcon | IconDefinition | faCheckSquare |
Icon used on selected meaves |
anyChildrenSelectedIcon | IconDefinition | faMinus |
Icon that will be put inside of the folder icon if it contains at least one ticked leaf |
allChildrenSelectedIcon | IconDefinition | faCheck |
Icon that will be put inside of the folder icon if all of its children are selected |
emptyFolderLabel | string | "This folder is empty" | The label to display inside empty branches |
contextMenus | NgxBootstrapTreeviewContextMenus | empty menus |
An object describing what your context menus on the tree should look like. If this is not specified, context menu will simply be disabled |
None of these inputs are mandatory. Just remember that the tree MUST have a datasource. Either by providing tree
or trees
, or by giving a mapper
+ item
or items
.
The purpose of this class is to map a given object to a Tree.
Its constructor takes 2 params, treeMap
which indicates how to map a tree and find its leaves and leafMap
which indicates how to map a leaf when we find some.
For more informations about all of this, check the Using mapper part.
This event is emitted whenever a leaf gets selected or unselected. It contains the leaf that was click along with a complete list of all the leaves that are ticked inside the tree.
Here is what it looks like:
class LeafClickedEvent {
public leaf: Leaf;
public selectedLeaves?: Leaf[];
}
This class and the next one are pretty self-explanatory. Just use them as interfaces if you ever need them.
class Tree {
children?: Tree[];
loadChildren?: Function;
label: string;
value: number | string;
}
class Leaf {
public value: string | number;
public label: string;
}
interface TreeMap {
value: string;
label: string;
// Contains the key that will point to the property of the source object that will contain children of the same type
// For a type T being the data source/branch type, this will point to the T[] type property
children?: string;
// Same idea as above, for type U indicating the datasource type, this will point to a U[]
leavesKey: string;
}
interface LeafMap {
value: string;
label: string;
}
Find a way to support custom objects as datasource(See Using Mapper part of the readme)- Boxes or custom right click to select/unselect an entire branch
- Async loading of children with a loadChildren callback (started working on it, paused right now)
- Possibility to disable animation and maybe add a set of fancy ones when folding/unfolding a branch
Allow a Tree array as an @Input() so this plugin can support multi-root trees(Done)- I'll probably have more ideas as this evolves
- Angular FontAwesome when it comes to icons
- Some of the Bootstrap classes