AngularJS Tree View Control

Did I mention that I love AngularJS? Oh, yes I did, on my previous post. Well, in case you didn’t believe me, this time I would like to share yet another small solution with AngularJS. By the way, I forgot to mention that I also use the awesome Twitter Bootstrap CSS framework, along with the also awesome Font Awesome font icons.

I made this simple tree view directive to simulate a file explorer. There was some more functionality specific to the project but I removed it for this demo. I intend to work a little bit more to make it into a more generic, configurable solution (suggestions accepted). In order to use it, you just need to add the necessary JavaScript and CSS files and drop the following HTML code in your page:

<div tree-view="structure" tree-view-options="options"></div>

Where structure is the JSON model containing the folders and files, and options is the tree view configuration (optional). If you don’t provide any, the default configuration is used.

The configuration options object currently accepts the following values:

Param Type Default Details
foldersProperty String "folders" Name of the property that contains the folders array in your model.
filesProperty String "files" Name of the property that contains the files array in your model.
displayProperty String "name" Name of the property that contains the name to be display both for files and folders.
collapsible Boolean true Whether or not the nodes are collapsible. If false, the nodes will always be expanded.
onNodeSelect function (Object, Array) undefined A callback function that is executed whenever a folder/file is selected. The first argument passed to the function is the actual node from the model, and the second argument is a dynamically generated array of all the ancestor nodes. This is useful to display breadcrums for the selected path.

The following is an example model and configuration that can be supplied to the tree view:

$scope.structure = { folders: [
    { name: 'Folder 1', files: [{ name: 'File 1.jpg' }, { name: 'File 2.png' }], folders: [
        { name: 'Subfolder 1', files: [{ name: 'Subfile 1' }] },
        { name: 'Subfolder 2' },
        { name: 'Subfolder 3' }
    { name: 'Folder 2' }

$scope.options = {
    onNodeSelect: function (node, breadcrums) {
        $scope.breadcrums = breadcrums;

The result should be similar to this:


The directive is recursive, so it should be able to handle any number of hierarchy levels (in theory). Source code in GitHub.

Update (8/28/2014): Added option mapIcon, which expects a function that takes a file node as the argument and must return a custom icon class (String). Sample usage included.

24 thoughts on “AngularJS Tree View Control

  1. Hey Axel. You speak spanish? Where I’d chat with you? I continue with my project, and I would like you help me clarify some doubts

  2. Hey, great work! Also, I have one question, can you put files in Root, not only folders? Thanks in advance πŸ™‚

      • Well, I supposed that it would be like that, and I tried. For example, I tried something like this:

        $scope.structure = { folders: [], files: [ {name:’some file’} ] };

        But, in this example, in root there is nothing. And for folders everything works perfect.

        Files that should be in root, are not shown, and, if I checked well, I included everything needed. Is there something I am missing maybe, if you can help? And thanks a lot πŸ™‚

    • You are right. There was a subtle bug that prevented the directive from rendering the files on the first level. I just pushed a quick fix to Github. Thanks for finding this issue!

    • Hi Axel,

      I saw your Index.html file. Please forget about previous question. Is there a way to return multiple fields from json?
      Right now I tried to feed this json and try to modified for own return value at onselect event.

      {folders:[{name:’SQ’,id:’1′,parent:’0′,type:’F’,files:[{name:’File 1.jpg’,id:’2′,parent:’1′,type:’I’},{name:’File 2.png’,id:’3′,parent:’1′,type:’I’}],folders:[{name:’Subfolder 1′,id:’4′,parent:’1′,type:’F’,files:[{name:’Subfile 1.txt’,id:’5′,parent:’4′,type:’I’}]},{name:’Subfolder 2′,id:’6′,parent:’1′,type:’F’},{name:’Subfolder 3′,id:’7′,parent:’1′,type:’F’}]},{name:’Folder 2′,id:’8′,parent:’0′,type:’F’}],files:[{name:’File 1.gif’,id:’9′,parent:’0′,type:’I’},{name:’File 2.gif’,id:’10’,parent:’0′,type:’I’}]}

      When I select, I want Id and type. How should I able to return it?

      • Hello,
        The onNodeSelect callback function passes the model that corresponds to the selected node (folder or file). So whatever fields you included in the original model will be available in the callback function’s first argument.

        $scope.options = {
            onNodeSelect: function (node, breadcrums) {
                // node is the original item in the model you passed in
                // You should have access to, node.parent, node.type... etc.
  3. Hello there, again! πŸ™‚
    One more time to say, beautiful solution for this problem!
    By the way, I have one question, if you could help. I customized much your directive for my problem, and it works perfectly. Although, I want to use angular-moment functions in it, specifically for showing dynamic ‘time ago’. So, in render() function, in variable ‘template’, among other things, I added:
    ‘ ‘.
    But, nothing shows. And function ‘findResultTakenTime’ works fine.
    Is there something I am missing? And, If you know, can I rely on angular-moment functions from custom directive?
    I hope I am not asking too much, and that you can point me to the right direction. πŸ™‚

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s