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:

Untitled

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.

Advertisements

Custom dropdown/auto-complete with AngularJS

Update (2015-09-17): Check out new Version 2 of this control.

I’ll admit it, I’m a big fan of AngularJS; it’s a great framework. If you consider yourself a serious front-end developer, you should really know about AngularJS. In our day to day work, we frequently find challenging requirements and problems that need to be solved efficiently and, why not, elegantly. And frameworks such as AngularJS help us achieve just that, and even turn our solutions into generic pieces of work that we can put in our tool box and use here and there across different projects. This time I will talk briefly about one such case. Hopefully it can be of use to someone else, too.

The problem

We all need to use an auto-complete box once in a while. There are many good solutions out there that are easy to use. But… they are usually limited to working with strings. On the other hand, regular select elements are great when you want to display names but use Id’s (or some sort of unique value) for your model and your business rules. But… they are pretty inflexible and “boring”. So, I needed and auto-complete box that worked also well with complex objects, and could integrate seamlessly with AngularJS.

The solution

Create an AngularJS directive from scratch. At least that was the only option I saw. And it didn’t turn out too bad after all. So here it is, Custom Select (sorry for the totally uncreative name).


<div custom-select ng-model="fruit" ng-options="f for f in fruits">
</div>

You may have noticed that the attributes look very similar to those of a regular AngularJS select directive (except for the additional custom-select attribute). Assuming you setup the appropriate values in your scope, you’ll get something like this.

Untitled

If you want to use JSON objects and have a display property and another property that gets saved to your model, you could use something like this:


<div custom-select ng-model="state" ng-options="s.id as s.name for s in states">
</div>

The end result would look very similar, but will work slightly different.

As a bonus, you could use a custom template for your dropdown items. Here’s an example:


<div custom-select ng-model="person" ng-options="t as t.name for t in people">

<div class="pull-left" style="width: 40px">
        <img ng-src="{{ t.picture }}" style="width: 30px" />
    </div>


<div class="pull-left">
        <strong>{{ t.name }}</strong>
        <span>{{ t.phone }}</span>
    </div>


<div class="clearfix"></div>

</div>

And the end result:
Untitled

If you liked it, you can grab the source code and the examples from Github.