7.1 KiB
AngularJS - Custom Directives
Lesson Objectives
- Explain what a custom directive is
- Create your own custom directive
- Include a template already in the HTML
- Reference a controller by name
- 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_directivescd custom_directivestouch app.js index.html product.htmlatom .
<!DOCTYPE html>
<html>
<head>
<script src='https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.2/angular.min.js'></script>
<script type="text/javascript" src="app.js"></script>
</head>
<body ng-app="MyApp">
</body>
</html>
const app = angular.module('MyApp', []);
Create your own custom directive
Here's our custom HTML element:
<product-title></product-title>
the full html:
file: index.html
<!DOCTYPE html>
<html >
<head>
<script src='https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.2/angular.min.js'></script>
<script type="text/javascript" src="js/app.js"></script>
</head>
<body ng-app="MyApp">
<product-title></product-title>
</body>
</html>
Here's how we define its behavior:
file: js/app.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)
};
});
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
<h3>
<p>product template</p>
This is the product name:
{{ctrl.name}}
</h3>
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
<!DOCTYPE html>
<html >
<head>
<script src='https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.2/angular.min.js'></script>
<script type="text/javascript" src="js/app.js"></script>
</head>
<body ng-app="MyApp">
<product></product>
<product-title></product-title>
<script type="text/ng-template" id='product-title.html'>
<h2>{{ctrl.name}}</h2>
</script>
</body>
</html>
file js/app.js
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...
<product-title awesome="super neat"></product-title>
and place them on your scope:
file: js/app.js
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
<body ng-app="MyApp">
<product></product>
<product-title awesome="super neat"></product-title>
<script type="text/ng-template" id='product-title.html'>
<h2>{{ctrl.name}}</h2>
{{myAttribute}}
</script>
</body>
You can change the @ to = and it will attempt to evaluate the attribute's value as javascript
file: js/app.js
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
<body ng-app="MyApp">
<product></product>
<product-title awesome="super neat"></product-title>
<script type="text/ng-template" id='product-title.html'>
<h2>{{ctrl.name}}</h2>
{{myAttribute}}
</script>
</body>
Lastly, you can also set the directive itself to be an attribute with a value
file: index.html
<div squirrel="flying squirrel"></div>
<script type="text/ng-template" id='partial3.html'>
Template 3!!
{{myAttribute}}
</script>
file: js/app.js
app.directive('squirrel', function(){
return {
templateUrl:'partial3.html',
controller: 'MainController',
controllerAs: 'main',
scope: {
myAttribute: '@squirrel'
}
}
});
app.controller('MainController', function(){
});
All the code
index.html
<!DOCTYPE html>
<html >
<head>
<script src='https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.2/angular.min.js'></script>
<script type="text/javascript" src="app.js"></script>
</head>
<body ng-app="MyApp">
<product></product>
<product-title awesome="super neat"></product-title>
<script type="text/ng-template" id='product-title.html'>
<h2>{{ctrl.name}}</h2>
{{myAttribute}}
</script>
<div squirrel="flying squirrel"></div>
<script type="text/ng-template" id='partial3.html'>
Template 3!!
{{myAttribute}}
</script>
</body>
</html>
product.html
<h3>
<p>product template</p>
This is the product name:
{{ctrl.name}}
</h3>
app.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'
});