# AngularJS - Custom Directives ## Lesson Objectives 1. Explain what a custom directive is 1. Create your own custom directive 1. Include a template already in the HTML 1. Reference a controller by name 1. Get values from other attributes placed on the directive tag ## Explain what a custom directive is You can create your own directives, just like ng-click, ng-submit, etc. This allows you to abstract away complicated/reusable code into an attribute, a class, a comment, or even your own HTML element! ## Set Up - `mkdir custom_directives` - `cd custom_directives` - `touch app.js index.html product.html` - `atom .` ```html ``` ```js const app = angular.module('MyApp', []); ``` ## Create your own custom directive Here's our custom HTML element: ```html ``` the full html: file: index.html ```html ``` Here's how we define its behavior: file: js/app.js ```javascript const app = angular.module('MyApp', []); app.directive('product', function(){ return { restrict: 'E', // E=element, A=attribute, C=class, M=comment, can be combined templateUrl: 'product.html', //template to replace directive element controller(){ //controller constructor function this.name = "arduino" }, controllerAs: 'ctrl' //how it should be instantiated (Controller as ctrl) }; }); ``` **NOTE** when using multiple custom directives, or even multiple controllers, make sure they are instantiated with different aliases (e.g. ctrl1, ctrl2, etc. as opposed to ctrl, ctrl, ctrl, etc.) Here's the external template referenced above: file: partials/product-title.html ```html

product template

This is the product name: {{ctrl.name}}

``` ## Include a template already in the HTML Just like with includes, we can specify templates that are ids in our HTML. Let's make a new on for product-title ## And Reference a controller by name You can reference a controller by name, instead of creating the controller within the directive itself file: index.html ```html ``` file js/app.js ```javascript app.directive('productTitle', function(){ return { restrict: 'E', // E=element, A=attribute, C=class, M=comment, can be combined templateUrl: 'product-title.html', //template to replace directive element controller: 'MainController', controllerAs: 'ctrl', //how it should be instantiated }; }); app.controller('MainController', function(){ this.name = 'main name' }); ``` ## Get values from other attributes placed on the directive tag You can add other attributes onto your directive tag... ```html ``` and place them on your scope: file: js/app.js ```javascript app.directive('productTitle', function(){ return { restrict: 'E', // E=element, A=attribute, C=class, M=comment, can be combined templateUrl: 'product-title.html', //template to replace directive element controller: 'MainController', controllerAs: 'ctrl', //how it should be instantiated scope: { myAttribute: '@awesome' } }; }); app.controller('MainController', function(){ this.name = 'main name' }); ``` Now you can reference the `myAttribute` property of scope in your html file: index.html ```html ``` **You can change the `@` to `=` and it will attempt to evaluate the attribute's value as javascript** file: js/app.js ```javascript const app = angular.module('MyApp', []); app.directive('product', function(){ return { templateUrl:'partial2.html', controller: 'MainController', controllerAs: 'main', scope: { myAttribute: '=awesome' } } }); app.controller('MainController', function(){ this.name = 'main name' }); ``` file: index.html ```html ``` Lastly, you can also set the directive itself to be an attribute with a value file: index.html ```html
``` file: js/app.js ```javascript app.directive('squirrel', function(){ return { templateUrl:'partial3.html', controller: 'MainController', controllerAs: 'main', scope: { myAttribute: '@squirrel' } } }); app.controller('MainController', function(){ }); ``` #### All the code index.html ```html
``` product.html ```html

product template

This is the product name: {{ctrl.name}}

``` app.js ```js const app = angular.module('MyApp', []); app.directive('product', function(){ return { restrict: 'E', // E=element, A=attribute, C=class, M=comment, can be combined templateUrl: 'product.html', //template to replace directive element controller(){ //controller constructor function this.name = "arduino" }, controllerAs: 'ctrl' //how it should be instantiated (Controller as ctrl) }; }); app.directive('productTitle', function(){ return { restrict: 'E', // E=element, A=attribute, C=class, M=comment, can be combined templateUrl: 'product-title.html', //template to replace directive element controller: 'MainController', controllerAs: 'ctrl', //how it should be instantiated scope: { myAttribute: '@awesome' } }; }); app.directive('squirrel', function(){ return { templateUrl:'partial3.html', controller: 'MainController', controllerAs: 'main', scope: { myAttribute: '@squirrel' } } }); app.controller('MainController', function(){ this.name = 'main name' }); ```