Rashim's Blog

Multi Select Drop-down in AngularJS

Posted on: July 8, 2014

After a huge gap, I have started working in web arena again. I had been working in desktop zone for recent few years on the technologies WPF/WCF, but, now here I am to dig down again with JavaScript and its rich set of open source libraries. While playing with some other JS Libraries, I have stunned to see the power of AngularJS and I am becoming a very good fan of it.  For this is so, I am about to write a small piece of things using AngularJS and would eager to continue with it more from now on. Since I had been working on MVVM pattern in WPF, AngularJS seems to me very much similar with the idea that I had been used to in WPF. However, I would love the way AngularJS gives us the features and its continuous growing.

AngularJS is a MV* framework for dynamic web apps which outlines abundant new concepts to properly manage our web application. It enhances HTML by incorporating new ideas which is called directives that could attach in our web pages with new attributes or tags. And by using those directives we can define very powerful templates directly in our HTML. Today I am going to introduce with such thing that is custom directives for Multi Select Drop Down.

Let’s move into code,


app.directive('dropdownMultiselect', function () {
    return {
        restrict: 'A',
        scope: {
            items: "=",
            selectedItems: "="
        },
        template:"<div class='dropdown col-md-1 offset0 margintLeft15 marginRigth5'                is_open='status.open'>" +
"<button type='button' class='btn btn-success dropdown-toggle' ng-click='openDropdown($event)'>" +
"Add <span class='caret'></span>" +
"</button>" +
"<div class='dropdown-menu expertDropList' >" +
"<div class='col-md-12 marginBottom15'>" +
"<div class='pull-right'>" +
"<button class='btn btn-sm btn-success' ng-click='closeDropDown()'>Close</button>" +
"<button class='btn btn-sm btn-success' ng-click='selectAll($event)'>Check All</button>" +
"<button class='btn btn-sm btn-success' ng-click='deselectAll($event);'>Uncheck All</button>" +
"</div>" +
"</div>" +
"<div data-ng-repeat='item in items' class='expertDropListBox' ng-click='handleClick($event)'>" +
"<input type='checkbox' ng-model='item.IsSelected' ng-click='clickItem($event)' ng-change='selectItem(item)' />" +
"{{item.Name}}" +
"</div>" +
"</div>" +
"</div>",
        controller: function ($scope) {
            $scope.handleClick = function ($event) {
                $event.stopPropagation();
            };
            $scope.status = {
                isopen: false
            };
            $scope.status = { isopen: false };
            $scope.openDropdown = function ($event) {
                if ($scope.items != undefined && $scope.items.length > 0) {
                    for (var index = 0; index < $scope.items.length; index++) {                         $scope.items[index].IsSelected = false;                     }                     if ($scope.selectedItems != undefined && $scope.selectedItems.length > 0) {
                        for (var selectedItemIndex = 0; selectedItemIndex < $scope.selectedItems.length; selectedItemIndex++) {
                            for (var itemIndex = 0; itemIndex < $scope.items.length; itemIndex++) {
                                if ($scope.selectedItems[selectedItemIndex].Id == $scope.items[itemIndex].Id) {
                                    $scope.items[itemIndex].IsSelected = true;
                                    break;
                                }
                            }
                        }
                    }
                }
                $event.stopPropagation();
                $scope.status.isopen = true;
            };
            $scope.selectAll = function ($event) {
                $scope.selectedItems = [];
                angular.forEach($scope.items, function (item) {
                    item.IsSelected = true;
                    $scope.selectedItems.push(item);
                });
                $event.stopPropagation();
            };
            $scope.deselectAll = function ($event) {
                angular.forEach($scope.items, function (item) {
                    item.IsSelected = false;
                });
                $scope.selectedItems = [];
                $event.stopPropagation();
            };
            $scope.selectItem = function (item) {
                if (item.IsSelected == false) {
                    for (var index = 0; index < $scope.selectedItems.length; index++) {
                        if (item.Id == $scope.selectedItems[index].Id) {
                            item.IsSelected = false;
                            $scope.selectedItems.splice(index, 1);
                            break;
                        }
                    }
                } else {
                    $scope.selectedItems.push(item);
                }
            };
            $scope.clickItem = function ($event) {
                $event.stopPropagation();
            };
            $scope.closeDropDown = function () {
                $scope.status.isopen = false;
                $event.stopPropagation();
            };
        }
    };
});

Though the code is self-explanatory I would like to explain a bit so that anyone can easily understand the technique behind this is. In order to make a directive, first, we need to set up ‘restirct’ which means how we would use this directive; would that be used as an element or attribute or comments; in my case this is ‘A’ that is it could be used as an attributes. Next, I define the isolated scope and define two properties ‘items’ and ‘selectedItems’ which will be filled up from the controller where  it has been used. And the responsibility of this directive is to give its parent controller to the selected Items. The template defines its look and the controller contains all the logic related to the templates binding property and its event stuffs that is we can think this controller as the presenter of the template. So, we can use this directive like in our HTML page like,


<div dropdown-multiselect="" items="FirstItems" selected-items="FirstSelectedItems"></div>
<div dropdown-multiselect="" items="SecondItems" selected-items="SecondSelectedItems"></div>

Now Module and Controller definition,


var app = angular.module('myApp', ['ui.bootstrap']);

app.controller('AppCtrl', ["$scope", function ($scope) {
    $scope.status = {
        isopen: false
    };

    $scope.FirstItems = [{ Id: 1, Name: "A", IsSelected: false },
            { Id: 2, Name: "B", IsSelected: false },
              { Id: 3, Name: "C", IsSelected: false },
                { Id: 4, Name: "D", IsSelected: false },
                  { Id: 5, Name: "E", IsSelected: false },
                    { Id: 6, Name: "F", IsSelected: false },
                      { Id: 7, Name: "G", IsSelected: false },
                        { Id: 8, Name: "H", IsSelected: false}];
    $scope.FirstSelectedItems = [];

    $scope.SecondItems = [{ Id: 1, Name: "A", IsSelected: false },
            { Id: 2, Name: "B", IsSelected: false },
              { Id: 3, Name: "C", IsSelected: false },
                { Id: 4, Name: "D", IsSelected: false },
                  { Id: 5, Name: "E", IsSelected: false },
                    { Id: 6, Name: "F", IsSelected: false },
                      { Id: 7, Name: "G", IsSelected: false },
                        { Id: 8, Name: "H", IsSelected: false}];
    $scope.SecondSelectedItems = [];

    var removeItem = function (items, item) {
        for (var index = 0; index < items.length; index++) {
            if (item.Id == items[index].Id) {
                item.IsSelected = false;
                items.splice(index, 1);
                break;
            }
        }
    };
    $scope.removeFirstItem = function (item) {
        removeItem($scope.FirstSelectedItems, item);
    };
    $scope.removeSecondItem = function (item) {
        removeItem($scope.SecondSelectedItems, item);
    };
} ]);

One more thing, you need to include the following files in your html page,

      angular.js
      ui-bootstrap-tpls-0.11.0.js
      bootstrap.min.css

That’s all. Nothing is tough or impressive here. Everything is straight forward and the code is also very easy to understand. The total code and live demo can be found in the Plunker.

Advertisements

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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 )

Google+ photo

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

Connecting to %s

%d bloggers like this: