*Note: the alias is only visible only whithin this div.*
**Include directive**
* **ng-include** - allows to include the specified file into your elements.
`
`
*Note: pass the name directly as a string using the single quotes `('...')`*
----
## Custom directive
Instead of using `ng-include` e.g. `
`
you can create a custom directive e.g. `
`.
The main benefit of the using the custom directives is that those allows you
to write HTML that expresses the behaviour of your application.
Directives can also be used for:
* Expressiong the Complex UI
* Calling events and registering event handlers
* Reusing common components
----
## Element Directive creation
*index.html*
*myApp.js*
app.directive('productDescription', function(){
return {
restrict: 'E',
templateUrl: 'product-description.html'
};
});
*product-description.html*
{{product.name}}
$250.00
*Note: dash in HTML translates to ...camelCase in JavaScript*
*Note: U still can use the regular directives on your custom one:*
----
## Attribute Directive creation
*index.html*
*myApp.js*
app.directive('productReview', function(){
return {
restrict: 'A',
templateUrl: 'product-review.html'
};
});
*product-review*
{{product.stars}} Stars
{{product.description}}
> Use Element Directives for UI widgets and Attribute Directives for
> mixin behaviors... like a tooltip.
----
## Add Controller to your Custom Directive
There are two solutions for this problem:
1. Use `ng-controller` on your custom directive:
2. Move the controller logic inside your directive with alias, to not forget to add it each time:
app.directive('productGallery', function(){
return {
restrict: 'E',
templateUrl: 'product-gallery.html',
controller:function(){
this.current = 0;
this.setCurrent = function(imageNumber){
this.current = imageNumber || 0;
};
},
controllerAs: 'galleryCtrl'
};
});
----
## Using $scope to get rid of Controller alias
Using of `$scope` as an function argument allows as to get
of controller alias and invoke the controller method directly with no reference to it.
app.directive('productGallery', function(){
return {
restrict: 'E',
templateUrl: 'product-gallery.html',
controller:function($scope){
// whatchout shared scope!
$scope.current = 0;
$scope.setCurrent = function(imageNumber){
$scope.current = imageNumber || 0;
};
}
};
});
Invocation to controller changed like this.
Before:
{{galleryCtrl.current}}
After:
{{current}}
----
## Isolating the $scope
Directives inherit their parent’s Scope by Default.
So, shared scope can be a problem cause all views will have a common data.
*(Similar case like with static fields & instance fields,
but even worse because actually properties are stored into the parent scope)*
By passing an object to the scope option, you are creating an isolate scope.
This tells the directive not to inherit or share the scope with other ones,
but to keep scope inside of itself *(like instance scope)*.
app.directive('productGallery', function(){
return {
restrict: 'E',
templateUrl: 'product-gallery.html',
// give this directive it's own scope
scope: {},
controller:function($scope){
$scope.albumName = '';
$scope.current = 0;
$scope.setCurrent = function(imageNumber){
$scope.current = imageNumber || 0;
};
}
};
});
Watch-out: Child no longer has access to the parent’s scope, cause it's not inherited anymore.
So, if some data from parent scope is needed we have to pass it from outside and store in our inner scope:
albumName="{{product.albumName}}"
A bit messy right? So, go ahead simplify it.
----
## Binding a String to Our Scope
There are 3 options when binding data to an isolate scope:
* **@** - Attribute string binding;
Binds a local/directive scope property to the evaluated value of the DOM attribute. So, u can use it with simple string values as well as with evaluated values `{{}}`
* **=** - Two-way model binding;
Binds a local/directive scope property to a parent scope property. So, u cant' use it with `{{}}`
The binding is bidirectional that allows the local/directive scope and the parent scope to share data.
* **&** - Callback method binding.
Use it if you don't need to share data with the parent, but you just want to call a function defined in the parent scope.
Moving back to our code:
app.directive('productGallery', function(){
return {
restrict: 'E',
templateUrl: 'product-gallery.html',
// give this directive it's own scope
scope: {
albumName: '='
},
controller:function($scope){
$scope.current = 0;
$scope.setCurrent = function(imageNumber){
$scope.current = imageNumber || 0;
};
}
};
});
So, we are passing in albumName, just like we would pass in variable to a function:
albumName="product.albumName"
Note: If u'd leave previous expression `{{product.albumName}}`, u have to use `@` instead e.g. `albumName: '@'`.
----
## How to Organize application Modules
It's better to keep the components behavior separately from each other.
For this purpose we've to create separate modules to encapsulate related directives into them:
* **app.js** – top-level module attached via `ng-app`;
* **gallery.js** – all the functionality for gallery and only galleries.
The flow is the following:
* Create new *.js file and declare the appropriate module:
*gallery.js*
(function() {
var app = angular.module('gallery-directives', []);
/*move your directives logic here*/
});
* Add new created module into main dependencies module:
(function() {
var app = angular.module('productStore', ['gallery-directives']);
* Add the module *js file into index.html:
. . .
* Move your directives into your module *.js file:
(function() {
var app = angular.module('gallery-directives', []);
app.directive("productGallery", function() {
return {
restrict: "E",
templateUrl: "product-gallery.html",
controller: function() {
this.current = 0;
this.setCurrent = function(imageNumber){
this.current = imageNumber || 0;
};
},
controllerAs: "gallery"
};
});
* Remove old directives from the main *.js file.
----
## Use Services
Use the Services to fetch the data from API.
Services give you additional functionality:
* Fetching JSON data from a web service with `$http`
* Logging messages to the JavaScript console with `$log`
* Filtering an array with `$filter`
*All built-in Services start with a `$` sign.*
Use $http Service is to make an async request to a server ...
* Using $http as a function with an options object:
$http({ method: 'GET', url: '/products.json' });
* Using one of the shortcut methods:
$http.get('/products.json', { apiKey: 'myApiKey' });
Both return a Promise object with `.success()` and `.error()`
If we fetch JSON via `$http`, the result will be automatically
decoded into JavaScript objects and arrays.
To use the Service in Controller we should use the following funky syntax:
// we need to store what this is
var store = this;
// we need to initialize products as an empty array to use it before data will be loaded
store.products = [ ];
// ------------------------------- Service names -- passed as arguments -> DI
app.controller('SomeController', [ '$http', '$log', function($http, $log) {
// $http returns a Promise, so the success() gets the data
$http.get('/products.json').success(function(data){
store.products = data;
})
} ]);
In addition to `get()` requests, $http can `post()`, `put()`, `delete()`
$http.post('/path/to/resource.json', { param: 'value' });
*The most of examples are taken from [AngularJS - ShapingUP course slides](http://courseware.codeschool.com/shaping-up-with-angular-js/Slides/level01-05.pdf)*
----
## see Also
* [Keynote: AngularJS Do the regular things](http://bloomlab.blogspot.com.ee/2015/09/keynote-angularjs-do-regular-things.html)
* [Keynote: AngularJS Basics](http://bloomlab.blogspot.com.ee/2015/09/keynote-angularjs-basic-short-notes.html)
* [AngularJS - Developer Documentation](https://docs.angularjs.org/guide)
* [AngularJS - ShapingUP course slides](http://courseware.codeschool.com/shaping-up-with-angular-js/Slides/level01-05.pdf)
* [AngularJS - StayingSharp course slides](http://courseware.codeschool.com/staying-sharp-with-angular-js/angular2-full-small.pdf)
* [Tutorials Point - AngularJS](http://www.tutorialspoint.com/angularjs/angularjs_directives.htm)
* [Tutorials Point - BestPractices](http://www.tutorialspoint.com/developers_best_practices/index.htm)
* [Keynote: Top JS frmeworks 2015](http://bloomlab.blogspot.com.ee/2015/03/top-javascript-frameworks-2015.html)
Good day. I was impressed with your article. Keep it up . You can also visit my site if you have time. Thank you and Bless you always.
ReplyDeleteOutsource Angularjs 2 Development in India