On our way down the directive path, we can't afford to overlook the concept of Isolated Scopes and how useful they are.
Let's set up an example of a directive with a text box bound to a model whose value is shown right next to it. It will look something like:
Let's set up an example of a directive with a text box bound to a model whose value is shown right next to it. It will look something like:
- <div ng-app="myApp">
- <kid></kid>
- </div>
- var app = angular.module('myApp', []);
- app.directive("kid", function() {
- return {
- restrict: 'E',
- template: '<input type="text" ng-model="task" /> {{ task }} <br/>'
- };
- });
This
will work simply as expected. You write the task for a kid in the text
box and the task will be shown along the side of the text box.
The question I'll put up is: What happens if we include multiple components "kid" in our template?
That's right, we'll see multiple text boxes as the result.
But one thing that you may not want is: When we write a task for a kid into the text box, the other kids also get the same message. See: jsfiddle
Technically, the "task" model is in the parent scope and it binds to the "task" model of each directive with the same value.This is called polluting the parent scope.
The entire purpose of re-using the directives must have been lost if not for the Isolated Scopes. I tried to explain their role in the earlier article. All we must do is create a space for this directive's own scope in which it will maintain some properties and have nothing to do with the parent scope or the scope of other directives. This can be done by assigning an empty object as the scope of our directive. This example explains how its done: jsfiddle
This isolated scope again comes with a problem that you may have already thought of. It cuts the connection of the directive's scope with its parent scope. What good is that? None!
As a solution to this problem, Angular provides us with the option to bind our isolated scope's expressions and objects with those of the parent scope. This can be done in several ways, on one of which I am going to throw some light on. Let's make our directives communicate back to their controllers.
Isolated scope "&"
First set up the controller in which we intend to place our directives. This controller will contain a function that in turn will be called by our directive. Let's see how:
The question I'll put up is: What happens if we include multiple components "kid" in our template?
That's right, we'll see multiple text boxes as the result.
But one thing that you may not want is: When we write a task for a kid into the text box, the other kids also get the same message. See: jsfiddle
Technically, the "task" model is in the parent scope and it binds to the "task" model of each directive with the same value.This is called polluting the parent scope.
The entire purpose of re-using the directives must have been lost if not for the Isolated Scopes. I tried to explain their role in the earlier article. All we must do is create a space for this directive's own scope in which it will maintain some properties and have nothing to do with the parent scope or the scope of other directives. This can be done by assigning an empty object as the scope of our directive. This example explains how its done: jsfiddle
This isolated scope again comes with a problem that you may have already thought of. It cuts the connection of the directive's scope with its parent scope. What good is that? None!
As a solution to this problem, Angular provides us with the option to bind our isolated scope's expressions and objects with those of the parent scope. This can be done in several ways, on one of which I am going to throw some light on. Let's make our directives communicate back to their controllers.
Isolated scope "&"
First set up the controller in which we intend to place our directives. This controller will contain a function that in turn will be called by our directive. Let's see how:
- var app = angular.module('myApp', []);
- app.controller('taskCtrl', function ($scope) {
- $scope.logTask = function (task) {
- alert(task + " is done!");
- };
- });
- app.directive("kid", function () {
- return {
- restrict: 'E',
- scope: {
- done: '&done' // '&' is used for referencing the expressions
- },
- template: '<input type="text" ng-model="task" /> {{ task }}<br/>'
- +'<button ng-click="done({task:task})">I\'m done!</button><br/>'
- };
- });
- <div ng-app="myApp">
- <div ng-controller="taskCtrl">
- <kid done="logTask(task)"></kid>
- </div>
- </div>
- done: '&'
Once
this attribute value, that holds the reference to the controller scope
method, is bound to the scope property of the directive, we can simply
use it in our directive's template. You can see how: jsfiddle
We shall now discuss other ways of binding data from a controller to an isolated scope. We will try to understand the difference among them and when to use them.
Isolated Scope “@”
Let's talk about setting up the isolated scope by data binding using the “@” sign. This tell the scope property of the directive to evaluate the attribute value as a string.
Anything that we pass on to the attribute will be evaluated as a string and assigned to the scope property of the directive. The following is how it's done:
We shall now discuss other ways of binding data from a controller to an isolated scope. We will try to understand the difference among them and when to use them.
Isolated Scope “@”
Let's talk about setting up the isolated scope by data binding using the “@” sign. This tell the scope property of the directive to evaluate the attribute value as a string.
Anything that we pass on to the attribute will be evaluated as a string and assigned to the scope property of the directive. The following is how it's done:
- <div ng-app="myApp">
- <div ng-controller="taskCtrl">
- <div kid name="{{var}}"></div>
- </div>
- </div>
- var app = angular.module('myApp', []);
- app.controller('taskCtrl', function ($scope) {
- $scope.var = "Shashank";
- });
- app.directive("kid", function () {
- return {
- scope: {
- name: '@'
- },
- template: '{{name}}'
- };
- });
See the working example: jsfiddle
Isolated Scope “=”
There might be cases when you don't just want to pass the string to the directive. You can pass an object into the directive, that updates inside the directive as soon as it is updated in the controller. But "@" can also do this for sure. What it can not do is bind the data another way round. I mean, when that object is updated inside the directive, "@" cannot update that object back into the controller. This can be done by "=". One thing you should understand is: "=" doesn't expect the controller's scope property to be enclosed within {{ }}. These brackets tell Angular to evaluate the enclosed property as a string. So we will remove these brackets when using "=" to bind data from the controller to the directive.
- <div ng-app="myApp">
- <div ng-controller="taskCtrl">
- Ctrl: <input type="text" ng-model="var">
- <div kid name="var"></div>
- </div>
- </div>
- var app = angular.module('myApp', []);
- app.controller('taskCtrl', function ($scope) {
- $scope.var = "Shashank";
- });
- app.directive("kid", function () {
- return {
- scope: {
- name: '='
- },
- template: 'Dir: <input type="text" ng-model="name">'
- };
- });
This
example shows two text boxes, the first one with the scope property
"var" of the controller scope. The second one has the isolated scope
property "name" of the directive. These two are bound to each other
using the "=" operator and it enables us to change any of the text box's
content to see the updated binding in the other. This is often called
"two-way binding". See it working here: jsfiddle
Source from :http://www.c-sharpcorner.com/UploadFile/2776f9/angularjs-isolated-scope/
No comments :
Post a Comment