Monday, October 8, 2018

Creating custom directives in AngularJS

10 comments

What are custom directives in AngularJS and how to use them ?

Angular JS custom directives are used to extend the functionality of HTML .Using custom directives we can attach a specific behavior to DOM elements or even transform the DOM elements and its children i.e we can create our own reusable html tags. Some examples of built-in directives are ngModel, ngRepeat etc .Directives are also registered on modules like controllers. To register a directive, you use the module.directive API. module.directive takes the normalized directive name followed by a factory function. This factory function should return an object with the different options to tell $compile how the directive should behave when matched.The factory function is invoked only once when the compiler matches the directive for the first time. You can perform any initialization work here. The function is invoked using $injector.invoke which makes it injectable just like a controller.

What is a normalized name ?
Html tags usually have '-' which separates different words in a tag.Eg : bootstrap classes like 'col-sm-3' .If you use this name in your javascript file(.js) it throws an error since there is a different usage for '-' i.e substraction. So this name with '-' in html is interpreted with camel casing. The name 'order-details' in html is interpreted as 'orderDetails' in javascript.

AngularJS provides support to create custom directives for following type of elements.
  • Element directives − Directive activates when a matching element is encountered.
  • Attribute − Directive activates when a matching attribute is encountered.
  • CSS − Directive activates when a matching css style is encountered.
  • Comment − Directive activates when a matching comment is encountered.

Now let’s see an example where you want to print the all the cart items in a json in a specific format (say in bootstrap columns). We have our cart items json :

$scope.orderItems = [{"QUANTITY" : 4,
                    "DESC" : "Chairs",
                    "AMOUNT": "50"
                    },
                    {"QUANTITY" : 1,
                    "DESC" : "Table",
                    "AMOUNT": "50"
                    },
                    {"QUANTITY" : 1,
                    "DESC" : "Monitor",
                    "AMOUNT": "250"
                    }]

We want to print this json data in the below tabular format with each row showing the details of each item in the json .



First lets create a directive which replaces its content with a html template . Here the html template should return a row with a particular order item’s data as shown in the above image .

app.directive("orderDetails",function () {
    console.log("directive called")
   
    return{
        templateUrl : 'orderDetails.html',
        scope    : {
            orderItem : "="
        }
    }
})


 As mentioned earlier we use the module.directive api to create a new directive . Here the normalized  name of the directive is orderDetails which is equivalent to order-details when we use it in html . The template url mentions the html template that should be used for this directive .  We can use the restrict property to restrict its usage to only an element or attribute or comment . Possible values are 'A'  (Attribute), 'E' (Element) , 'C' (Class), 'M' (Comments) . Please refer the documentation for more details .

This new directive has access to its parent model through $scope and since this directive is reusable and if used in different places it might be dangerous since the parent controller's data will be accessible everywhere. To avoid this problem we have the concept of isolated scope i.e we add another property 'scope' on the directive  . Now, the scope is isolated and this new property on the directive acts as the model for the directive. If you want to pass values from the json to the directive you pass them as attributes or objects . Here we have used the two way binding ‘=’ to bind each order Item in the  json  to the variable orderItem .If its just an attribute and not an object use '@' . If its a function use '&' . Since the name used in the html and directive matches (orderItem) I have just used ‘=’ . If not we need to pass the var name after ‘=’  (“=orderItem”) .

Now , how do we use this directive in our html ?
 Use the tag <order-details> like any other html element . Since we want to repeat this directive on each item in the json use ng-repeat to print all the items in the json.

<!--custom directive which prints each item in the json -->
<order-details order-item="orderItem" ng-repeat="orderItem in orderItems"></order-details>

Custom Directives also have  powerful features like compile , link and transclusion which are rarely used . These features help to modify the DOM during the compile and link phase . Refer the angular documentation  for more details - https://docs.angularjs.org/guide/directive .

Please refer the plunker https://next.plnkr.co/edit/Y1n7A2muJeqzRVjO for a demo and complete implementation of this example.




10 comments :

  1. Great! Thanks for sharing the useful blog about creating custom directives in AngularJS.

    Web Designing company in Coimbatore

    ReplyDelete
  2. Amazing blog.
    This is a nice article which is good informative for me. Thanks for sharing.
    Full Stack Online Training

    ReplyDelete
  3. This post is so useful and informative. Keep updating with more information.....
    Best RPA Training in Bangalore
    Robotic Process Automation Training in Bangalore

    ReplyDelete