Rashim's Blog

Posts Tagged ‘Directive


Angular directive is a powerful feature to develop your own DOM marker that tells Angular HTML compiler to attach its functionality.  By using this feature, we could easily develop any html attributes (which we could consider as a control) that would give us to meet our business requirements. Couple of days ago I was assigned to develop a search enable input box which makes me to start developing a new directive for these purposes. Today I would like to share how I developed a new directive for search enable and autocomplete input. This is very easy and straight forward and anyone who is well-versed about angular js could easily develop this. Let’s have a bit explanation of the code,

First, the template that would use for custom input box which will work as a search input and autocomplete as well,

<div>
    <div>
        <input type="text"
               ng-keydown="handleKeyDown($event)"
               ng-model="searchText"
               ng-change="handleSearch()" />
    </div>
    <ul class="suggestions-list" ng-show="isOpen">
        <li ng-repeat="suggestion in items"
            ng-click="addToSelectedItem($index)"
            ng-mouseover="$parent.selectedIndex=$index"
            ng-class="{active : selectedIndex===$index}">{{suggestion.displayName}}</li>
    </ul>
</div>

Here, in the input box, the observable property is searchText and each time you change input value of the input text handleSearch will get executed and if there is any result it has got from its consumer to display, it just open the drop down and display the result from where we can choose.
Now the directive definition and functionality implementation,

app.directive('autoComplete', [function () {
    var autoComplete = {
        restrict: 'AE',
        scope: {
            selectedItem: "=",
            onSearch: '&'            
        },
        controller: function ($scope) {
            $scope.isOpen = false;
            $scope.selectedIndex = -1;
            $scope.searchText = '';
            $scope.items = [];          
            $scope.handleKeyDown = function (event) {
                if (event.keyCode === 40) {
                    event.preventDefault();
                    if ($scope.selectedIndex + 1 !== $scope.items.length) {
                        $scope.selectedIndex++;
                    }
                }
                else if (event.keyCode === 38) {
                    event.preventDefault();
                    if ($scope.selectedIndex - 1 !== -1) {
                        $scope.selectedIndex--;
                    }
                }
                else if (event.keyCode === 13) {
                    $scope.addToSelectedItem($scope.selectedIndex);
                    $scope.isOpen = false;
                }
            },

            $scope.handleSearch = function () {
                $scope.selectedIndex = -1;
                $scope.isOpen = false;
                $scope.items = [];
                if ($scope.searchText) {
                    var searchData = $scope.onSearch({ searchKey: $scope.searchText });
                    $scope.items = [];
                    if (searchData && searchData.length > 0) {
                        searchData.forEach(function(data) {
                            $scope.items.push(data);
                        });
                        $scope.isOpen = true;
                    } else {
                        $scope.selectedItem = $scope.searchText;
                    }
                }
            }

            $scope.addToSelectedItem = function (index) {
                $scope.selectedItem = $scope.items[index];
                $scope.searchText = $scope.selectedItem.displayName;
                $scope.isOpen = false;
            }            
        },
        templateUrl: 'autocomplete-template.html'
    };

    return autoComplete;
}]);

In this code we restrict the consumer to supply two things: one is selected Item, another one is search handler. selectedItem is needed because when you select any data from drop down ,it needs to send this data to its consumer and search handler is needed to get the search result from the consumer. That’s it; rest of the code is self-explanatory, and nothing tough as well as no extra work has been done to mention here. Source code is available here.


Almost all web based projects, where location/address is included, we might require mapping service to show the exact location or street view on the page. Thanks to Google to give us such amazing service application, yes I am talking about Google Maps which offers street maps and street view perspective and many more. To get the map rendered in the web page using Angular JS is pretty easy and straight forward. I am going to show you how we can do this,

For this is so, I have created a directive so that I could reuse it throughout the application as an html tag. To locate the area, we might put its Latitude and Longitude or we might put just a valid address. The following directive could be used while we have the latitude and longitude for a particular area,


app.directive('areaBasedGoogleMap', function () {
    return {
        restrict: "A",
        template: "<div id='areaMap'></div>",
        scope: {           
            area: "=",
            zoom: "="
        },
        controller: function ($scope) {
            var mapOptions;
            var map;           
            var marker;

            var initialize = function () {                                
                mapOptions = {
                    zoom: $scope.zoom,
                    center: new google.maps.LatLng(40.0000, -98.0000),
                    mapTypeId: google.maps.MapTypeId.TERRAIN
                };
                map = new google.maps.Map
(document.getElementById('areaMap'), mapOptions); }; var createMarker = function (area) { var position = new google.maps.LatLng
(area.Latitude, area.Longitude); map.setCenter(position); marker = new google.maps.Marker({ map: map, position: position, title: area.Name }); }; $scope.$watch("area", function (area) { if (area != undefined) { createMarker(area); } }); initialize(); }, }; });

And this directive might be used while we have a valid address,


app.directive('addressBasedGoogleMap', function () {
    return {
        restrict: "A",
        template: "<div id='addressMap'></div>",
        scope: {
            address: "=",
            zoom: "="
        },
        controller: function ($scope) {
            var geocoder;
            var latlng;
            var map;
            var marker;
            var initialize = function () {
                geocoder = new google.maps.Geocoder();
                latlng = new google.maps.LatLng(-34.397, 150.644);
                var mapOptions = {
                    zoom: $scope.zoom,
                    center: latlng,
                    mapTypeId: google.maps.MapTypeId.ROADMAP
                };
                map = new google.maps.Map
(document.getElementById('addressMap'), mapOptions); }; var markAdressToMap = function () { geocoder.geocode({ 'address': $scope.address },
function (results, status)
{ if (status == google.maps.GeocoderStatus.OK) { map.setCenter(results[0].geometry.location); marker = new google.maps.Marker({ map: map, position: results[0].geometry.location }); } }); }; $scope.$watch("address", function () { if ($scope.address != undefined) { markAdressToMap(); } }); initialize(); }, }; });

And in html we can use these directives like the way,

<div address-based-google-map address="Adress" zoom="16"></div>
<div area-based-google-map area="Area" zoom="8"></div>

Finally Module and Controller definition,


var app = angular.module("Main_app", []);

app.controller("MainController", ["$scope", 
function MainController($scope) 
{    
    $scope.Adress = "American University,4400 Massachusetts Ave NW,Washington, DC 20016";
    $scope.Area = { 
                    Name: "Melbourne", 
                    Latitude: -37.8140000, 
                    Longitude: 144.9633200 
                  };
}]);

One more thing, you need to include following JS file to your html page,


angular.js
https://maps.googleapis.com/maps/api/js?sensor=false 

And the style,


 #areaMap, #addressMap
  {
    height: 400px;
    width: 400px;
    margin: 10px;
    padding: 10px;
  }

Very easy stuff but effective enough!!! Download Source Code


%d bloggers like this: