https://www.3pillarglobal.com/insights/angularjs-understanding-directive-scope

---------------------------------------------------------------------------------------------------

In the previous post, we created custom AngularJS directives. However, we did not address how directives manipulate data objects that are defined in the Angular app. In certain use cases, the directive might need to use the objects and functions defined in the controller—manipulate their values and make calls to the functions. In this post we shall explore how this is done from within a directive.

SCOPE IN A DIRECTIVE

How does a directive interact with the page controller? How can objects be passed to the directive? How are functions defined in scope of the controller called from inside the directive?

Well, all of the directives have a scope associated with them. This scope object is used for accessing the variables and functions defined in the AngularJS controllers, and the controller and link functions of the directive. By default, directives do not create their own scope; instead they use the scope of their parent, generally a controller (within the scope of which the directive is defined).

We can change the default scope of the directive using the scope field of the DDO (Data Definition Object). Note that scope is a property of the directive, just like restrict, template, etc. The value of the scope field defines how the scope of the directive will be created and used. These values are ‘true’, ‘false,’ and ‘{}’.

Let’s start exploring the usage of each of these.

SCOPE: FALSE

This is the default value of scope in the directive definition. In this case, the directive has the same scope as its parent controller. The following is an example of creating a movie directive:

We create a controller and define a movie title in it. This movie will then be modified in the directive.

  • Creating an Angular app and controller

    var movieApp = angular.module("movieApp",[]);
    
    movieApp.controller("movieController",function($scope){
    $scope.movie = "Ice Age";
    });
  • Defining the directive
    movieApp.directive("movieDirective", function(){
    return {
    restrict: "E",
    scope: false,
    template: "<div>Movie title : {{movie}}</div>"+
    "Type a new movie title : <input type='text' ng-model='movie' />"
    };
    });
  • Finally, embedding the directive in HTML
    <div ng-app="movieApp">
    <div ng-controller="movieController">
    <h2>Movie: {{movie}}</h2>
    Change Movie Title : <input type='text' ng-model='movie'/>
    <movie-directive></movie-directive>
    </div>
    </div>

In the code snippet given above, the movie name in the heading tag takes value from the controller’s scope. Note that the movie title in the directive template also gets its value from the controller scope, that is, Ice Age. Since the scope of the directive is not set, it uses the parent scope. Therefore, modifying the movie title in the directive text box modifies the movie title in the heading tag also. Similarly, changes done to the movie title in the heading tag are reflected in the directive. But this restricts the directive to be used outside the controller scope, which reduces the directive’s reusability.

Let’s see the output:

On changing the Movie Title in the text box above:

The Movie Title in all of the places gets modified.

SCOPE: TRUE

Let’s change the scope field of the directive in the last example to true

scope: true

In this case,

In this case, the movie title in both the header section and the directive is initialized to the same value defined in the controller’s scope, Ice Age.

Now, modifying the movie title in the directive modifies the directive content only, not the heading content.

In order to see whether changing the heading content changes the directive content, let’s modify the movie title in the text box following the heading tag.

<div ng-app="movieApp">
<div ng-controller="movieController">
<h2>Movie: {{movie}}</h2>
Change Movie Title : <input type='text' ng-model='movie'/>
<movie-directive></movie-directive>
</div>
</div>

Entering the movie title in this text box changes the movie title in the heading tag only and not in the directive.

What happened here? This time the directive got its own scope! Angular creates a new scope for the directive that is inherited from the parent (controller) scope.

There is one thing to note here: If the content in the text box in the header section is changed first, then this change is also reflected inside the directive. However, after the movie title in the directive is changed, any changes made to the heading text no longer affect the directive content. The explanation for this is that the ng-model creates a new movie variable only after the text box value is changed. Until then, it refers to the value in the parent scope.

So here the content of both the text boxes change when the header section text box is modified first.

SCOPE: {}

This is how the directive gets its isolated scope. We pass an object for the scope field in this case. This way, the scope of the directive is not inherited from the parent and is instead completely detached from it. Thus, the directive has an isolated scope.

To see it in action, we modify the directive code:

movieApp.directive("movieDirective", function(){
return {
restrict: "E",
scope: {},
template: "<div>Movie title : {{movie}}</div>"+
"Type a new movie title : <input type='text' ng-model='movie' />"
};
});

Note that the directive no longer takes the movie title defined in the controller. It has its own model, ‘movie,’ defined in the template. In addition, the changes to the controller content in no way affect the directive. The directive has complete control over its contents – an isolated scope!

Even though the directive has its own scope, there may be scenarios where the directive needs to exchange data with the parent. AngularJS covers that too, by allowing communication between the parent scope and the directive. The directive can gain access to the parent scope by using some special symbols known as prefixes.

ISOLATED SCOPE – PREFIXES

In the case of an isolated scope, the directive scope is completely unaware of its parent’s scope. So how does a directive access the parent scope objects or make calls to the methods?

The directive scope uses prefixes to achieve that. Using prefixes helps establish a two-way or one-way binding between parent and directive scopes, and also make calls to parent scope methods. To access any data in the parent scope requires passing the data at two places – the directive scope and the directive tag.

  1. Passing data to the directive scope:

    movieApp.directive("movieDirective", function(){
    return {
    restrict: "E",
    scope: {
    movie: ‘=’
    },
    template: "<div>Movie title : {{movie}}</div>"+
    "Type a new movie title : <input type='text' ng-model='movie' />"
    };
    });
  2. Passing data in the directive tag
    <movie-directive movie="movie"></movie-directive>

Here movie is a property of the directive scope and can be accessed as a directive data. Note that the behavior of these properties defined in the directive scope depends how they are bound to the directive – also known as prefixes – provided. These prefixes are used to bind the parent scope’s methods and properties to the directive scope.

There are 3 types of prefixes in AngularJS:

  1. ‘@’ – Text binding / one-way binding
  2. ‘=’ – Direct model binding / two-way binding
  3. ‘&’ – Behavior binding / Method binding

Let’s continue with the example of the movie directive and add more properties to the scope method so as to understand all of these prefixes.

In this example, we add a rating property to the existing movie directive. Now when the movie is rated, this value is modified in the directive scope and is reflected there only, not in the header scope. However, when the movie name is changed in the movies section, the change is also reflected in the header scope. Finally, a method call displays the movie name in an alert box. The following code puts all of this in action.

  • Modifying the controller

    movieApp.controller("movieController",function($scope){
    $scope.movie = "Ice Age";
    $scope.rating = 5;
    $scope.display = function(movie) {
    alert("Movie : " + movie);
    }
    });
  • Modifying the directive
    movieApp.directive("movieDirective", function(){
    return {
    restrict: "E",
    scope: {
    movie: '=',
    rating: '@',
    display: '&'
    },
    template: "<div>Movie title : {{movie}}</div>"+
    "Type a new movie title : <input type='text' ng-model='movie' />"+
    "<div>Movie rating : {{rating}}</div>"+
    "Rate the movie : <input type='text' ng-model='rating' />"+
    "<div><button ng-click='display(movie)'>View Movie</button></div>"
    };
    });
  • Passing the fields in the directive tag
    <div ng-app="movieApp">
    <div ng-controller="movieController">
    <h2>Movie Name : {{movie}}</h2>
    <h3>Rating : {{rating}}</h3>
    <movie-directive movie="movie" rating="{{rating}}" display="display(movie)">
    </movie-directive>
    </div>
    </div>

And the output:

After clicking the  View Movie button, we have an alert pop up as:

Let’s dissect this code. There is a 2-way binding in the movie property. That is, any changes made to the movie title in either the controller or the directive will reflect over onto the other. This is similar to the setting scope: false!

The rating property has a 1-way binding. Thus, changes made in the directive reflect only there. Also note the difference in passing movie and rating in the in the directive tag. Properties that have 1-way binding are enclosed within parenthesis {{}}.

Note that the display function bound in the directive is defined in the controller (parent) scope. Thus, the directive is able to call controller methods.

DIRECTIVE FUNCTIONS

In the example given above, though the directive has an isolated scope, it uses controller methods and thus is able to interact with the controller. However, because a directive is an independent unit, it should also have the capability of defining its own methods. For this, the DDO of the directive has a field link. Let’s modify the example above.

  • Modifying the controller to remove the display method from it

    movieApp.controller("movieController",function($scope){
    $scope.movie = "Ice Age";
    $scope.rating = 5;
    });
  • Defining the display method in the link field of the directive
    movieApp.directive("movieDirective", function(){
    return {
    restrict: 'E',
    scope: {
    movie: '=',
    rating: '@',
    display: '&'
    },
    template: "<div>Movie title : {{movie}}</div>"+
    "Type a new movie title : <input type='text' ng-model='movie' />"+
    "<div>Movie rating : {{rating}}</div>"+
    "Rate the movie : <input type='text' ng-model='rating' />"+
    "<div><button ng-click='display(movie)'>View Movie</button></div>", link: function($scope, element, attrs) {
    $scope.display = function(movie) {
    alert("Movie : " + movie);
    }
    }
    };
    });

The output is:

After clicking the View Movie button, we have an alert pop up as:

This output is the same as the previous case, when the display method was defined in the controller.

BUT WHY THE ISOLATED SCOPE?

Note that we can access the parent scope objects if we set the scope field to true or false. However, since directives are independent components, the best practice would be to pass all of the objects and methods that the directive intends to use in the directive tag itself, and further define them in the DDO.

Implementing functionality in AngularJS becomes more modular and reusable if the code has directives defined. And the application of directives becomes more maintainable and robust if the directive scope is well constructed

ANGULARJS: UNDERSTANDING DIRECTIVE SCOPE的更多相关文章

  1. angularjs中的directive scope配置

    angularjs中的directive scope配置 定义directive其中重要的一环就是定义scope,scope有三种形式: 默认的scope,DOM元素上原有的scope scope: ...

  2. AngularJs学习笔记--Scope

    原版地址:http://code.angularjs.org/1.0.2/docs/guide/scope 一.什么是Scope? scope(http://code.angularjs.org/1. ...

  3. AngularJS之directive

    AngularJS之directive AngularJS是什么就不多舌了,这里简单介绍下directive.内容基本上是读书笔记,所以如果你看过<AngularJS up and runnin ...

  4. Angularjs之directive指令学习笔记(二)

    1.Directive的五个实例知道driective作用.其中字段restrict.template. replace.transclude.link用法 参考文章链接地址:http://damoq ...

  5. 前端angularJS利用directive实现移动端自定义软键盘的方法

    最近公司项目的需求上要求我们iPad项目上一些需要输入数字的地方用我们自定义的软键盘而不是移动端设备自带的键盘,刚接到需求有点懵,因为之前没有做过,后来理了一下思路发现这东西也就那样.先看一下实现之后 ...

  6. Angularjs的directive封装ztree

    一般我们做web开发都会用到树,恰好ztree为我们提供了多种风格的树插件. 接下来就看看怎么用Angularjs的directive封装ztree <!DOCTYPE html> < ...

  7. AngularJS自定义Directive初体验

    通常我们这样定义个module并随之定义一个controller. var app = angular.module('myApp', []); app.controller('CustomersCo ...

  8. angularjs 中的scope继承关系——(2)

    转自:http://www.lovelucy.info/understanding-scopes-in-angularjs.html angularjs 中的scope继承关系 ng-include ...

  9. angularJS中directive父子组件的数据交互

    angularJS中directive父子组件的数据交互 1. 使用共享 scope 的时候,可以直接从父 scope 中共享属性.使用隔离 scope 的时候,无法从父 scope 中共享属性.在 ...

随机推荐

  1. SHH框架的搭建

    建立一个Web项目,然后导入如下包 l  struts2包:在struts2-blank.war下的lib目录下,以及struts-2.3.15.1\lib下的struts和spring整合的插件包s ...

  2. 汕头市队赛 SRM14 T1 计算几何瞎暴力

    计算几何瞎暴力 (easy.pas/c/cpp) 128MB 1s 在平面上,给定起点和终点,有一面墙(看作线段)不能穿过,问从起点走到终点的最短路程. 输入格式 输入一行,包含8个用空格分隔的整数x ...

  3. .net yield return

    yield在迭代器块中用于向枚举数对象提供值或发出迭代结束信号.它的形式为下列之一: yield return <expression>; yield break; 计算表达式并以枚举数对 ...

  4. 培训补坑(day5:最小生成树+负环判断+差分约束)

    补坑补坑((╯‵□′)╯︵┻━┻) 内容真的多... 一个一个来吧. 首先是最小生成树. 先讲一下生成树的定义 生成树就是在一张图上选取一些边,使得整个图上所有的点都连通. 那么我们要求的最小生成树有 ...

  5. fmap为什么可以用function作为第二个参数

    看看fmap的类型 fmap :: Functor f => (a -> b) -> f a -> f b 很明显的,第一个参数是function,第二个参数是functor的 ...

  6. linux内核情景分析之exit与Wait

    //第一层系统调用 asmlinkage long sys_exit(int error_code) { do_exit((error_code&0xff)<<8); } 其主体是 ...

  7. c# GDI画图 双缓冲画图分析

    双缓冲绘图分析  1.Windows 绘图原理  我们在 Windows 环境下看到各种元素,如菜单.按钮.窗口.图像,从根本上说,都是“画”出来的.这时的屏幕,就相当于一块黑板,而 Windows ...

  8. python--cProfile,memory_profiler,psutil

    关于测试代码用了多长时间,我们之前介绍了timeit.相较于timeit,python中还有一个更加强大的模块,cProfile模块 (提到cProfile,其实还有一个profile,但profil ...

  9. Font Awesome 字体使用方法, 兼容ie7+

    WebFont 技术可以让网页使用在线字体,而无需使用图片,从而有机会解决开头设计师提到的问题.它通过 CSS 的@font-face语句引入在线字体,使用 CSS 选择器指定运用字体的文本,与此同时 ...

  10. 利用NPOI组件产Excel完整操作

    最终还是要使用NPOi了.刚开始做的是用com组件,发现如果本机不按照excel就不能使用,后来把其中一支改为了用Itextsharp产生pdf,但是还有几支批次要产生Excel,只能改用NPOI了. ...