# 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'
});
```