本篇介绍指令的最后两个属性,require和controller

当一个指令需要和父元素指令进行通信的时候,它们就会用到这两个属性,什么意思还是要看栗子:

html:

<outer‐directive>
<inner‐directive></inner‐directive>
</outer‐directive>

这里有两个指令,一个outer-directive指令元素,它里面又有一个inner-directive指令元素.

js:

app.directive('outerDirective',function(){
return {
scope: {},
restrict: 'AE',
controller: function($scope,$compile,$http){
this.addChild = function(nestedDirective){ //this指代controller
console.log('Got the message from nested directive' + nestedDirective.message);
}
}
}
});
app.directive('innerDirective',function(){
return {
scope: {},
restrict: 'AE',
require: '^?outerDirective',
link: function(scope,elem,attrs,ctrl){
//第四个参数是你require的controller实例
scope.message = 'Hi, Parent directive';
ctrl.addChild(scope);
}
};
});

在父元素指令里定义controller方法:

function($scope,$compile,$http){
this.addChild = function(nestedDirective){ //this指代controller
console.log('Got the message from nested directive' + nestedDirective.message);
}
}

controller方法是一个构造函数,可以给它添加对象的方法(什么是对象的方法看这里:mvc-javascript-web-application / 01.MVC和类 / 1.创建类库 / ex1.3(对象的方法).html).

在子元素指令里定义require属性:require: '^?outerDirective',表示向外层寻找outerDirective指令,直到找到为止.注意:向外层寻找,也包括了自己本身,也就是说,自己可以寻找到自己身上的其它指令.

'?'的作用是如果找不到也不会报错.

定义了require属性后,link函数的第四个参数ctrl就是require到的指令的controller方法的实例.所以ctrl就有了addChild方法了.

下面看一个难一点的栗子:

angular学习笔记(三十)-指令(9)-一个简单的指令示例这个栗子是单个子菜单的展开收起,下面使用require和controller,来扩展这个应用,改成多个菜单,要求点击某个菜单的时候展开此菜单,而其余菜单都收起:

如下过程:

html:

<!DOCTYPE html>
<html ng-app="accordionModule">
<head>
<title>20.10 指令-accordion</title>
<meta charset="utf-8">
<link href="../bootstrap.css" rel="stylesheet">
<script src="../angular.min.js"></script>
<script type="text/ng-template" id="vertical.html">
<div class="btn-group-vertical" ng-transclude>
</div>
</script>
<script type="text/ng-template" id="text.html">
<div class="btn-group">
<button class="btn btn-default dropdown-toggle" type="button" ng-click="toggle()">{{title}}<span class="caret"></span></button>
<ul class="dropdown-menu" ng-show="ifShow" ng-transclude></ul>
</div>
</script>
<script src="script.js"></script>
<style type="text/css">
body{
padding:40px
}
</style>
</head>
<body>
<div ng-controller="accordionCtrl">
<accordion>
<expander ng-repeat="list in lists" my-title="{{list.title}}">
<li ng-repeat="content in list.contents">
<a href="">{{content}}</a>
</li>
</expander>
</accordion>
</div>
</body>
</html>

js:

/*20.10 指令*/
var accordionModule = angular.module('accordionModule',[]);
accordionModule.controller('accordionCtrl',function($scope){
$scope.lists = [
{title:'标题1',contents:['bunny1','cat1','dog1']},
{title:'标题2',contents:['bunny2','cat2','dog2']},
{title:'标题3',contents:['bunny3','cat3','dog3']},
{title:'标题4',contents:['bunny4','cat4','dog4']},
{title:'标题5',contents:['bunny5','cat5','dog5']},
{title:'标题6',contents:['bunny6','cat6','dog6']},
{title:'标题7',contents:['bunny7','cat7','dog7']},
{title:'标题8',contents:['bunny8','cat8','dog8']}
]
});
accordionModule.directive('accordion',function(){
return {
restrict:'EA',
replace:true,
templateUrl:'vertical.html',
transclude:true,
controller:function(){
this.expanders = [];
this.closeAll = function(scope){
angular.forEach(this.expanders,function(expander){
if(scope!=expander)
expander.ifShow = false;
})
};
this.addExpander = function(scope){
this.expanders.push(scope)
}
}
}
});
accordionModule.directive('expander',function(){
return {
restrict:'EA',
replace:true,
templateUrl:'text.html',
transclude:true,
scope:{title:'@myTitle'},
require:'^?accordion',
link:function(scope,ele,attrs,ctrl){
scope.ifShow = false;
ctrl.addExpander(scope);
scope.toggle = function(){
ctrl.closeAll(scope);
scope.ifShow = !scope.ifShow;
}
}
}
});

下面来解释这个应用:

1. accordion指令的controller的实例也就是link函数的第四个参数ctrl

2. 将expander指令进行ng-repeat,渲染出多个子菜单.

3. 由于这些子菜单是互相有关联而非独立存在的,所以将他们放在一个accordion指令中.

4. 绑定数据模型都和单独的expander一样,唯一不同的是:

1) link函数中调用ctrl的addExpander方法,将每个expander的独立scope压入ctrl的expanders数组中.

2) toggle()方法,它调用了accordion指令的controller的实例的方法.收起除了当前点击项以外其余的菜单.

5. 注意ctrl是唯一的ctrl,而不是每次都实例化出一个新的实例.虽然有多个expander,但是它的ctrl指向的是同一个实例,所以expanders数组是唯一的.

6. 这里expanders数组里存放是每个expander的scope,为什么是scope而不是element呢? 因为closeAll方法需要修改指令独立作用域下的ifShow的,所以这里数组里存放scope比较好写.

完整代码: https://github.com/OOP-Code-Bunny/angular/blob/master/OREILLY/20.10%20%E6%8C%87%E4%BB%A4.html

https://github.com/OOP-Code-Bunny/angular/blob/master/OREILLY/script.js

最新文章

  1. Excel自文本导入内容时如何做到单元格内换行
  2. CA 证书
  3. css3内容持续更新ing
  4. Oracle存储过程学习备忘
  5. python lambda函数详细解析(面试经常遇到)
  6. POJ3461 Oulipo KMP算法
  7. python无私有成员变量
  8. pes and ts stream, how to convert
  9. Google GFS文件系统深入分析
  10. Android窗口管理服务WindowManagerService显示Activity组件的启动窗口(Starting Window)的过程分析
  11. Yii在nginx下多目录rewrite
  12. IBM新合作伙伴计划助力企业转型升级
  13. RE : 球体波浪倒计时
  14. SUCTF--WEB
  15. nim读写注册表的小例子
  16. 深入理解JVM——对象
  17. 《Essential C++》读书笔记 之 基于对象编程风格
  18. win7 下安装使用 nginx 出现500错误
  19. 使用 PHP 框架 Yii 访问 MS SQL 的尝试
  20. 不能存在多个@ManyToMany(fetch=FetchType.EAGER)

热门文章

  1. Node.js相关——package概念及NPM
  2. jenkins shell脚本自动化构建阿里云k8s上应用
  3. c++ 11 override final
  4. 【备份】使用mysqldump 实现rename database name(mysql数据库改名称)
  5. JavaScript调用App原生代码(iOS、Android)通用解决方案
  6. JetBrains C++ IDE CLion配置与评测
  7. hibernate的findByExample 外键参数查询解决方案
  8. C# 使用Xamarin开发Android应用程序
  9. java udp 广播
  10. htmlentities、addslashes 、htmlspecialchars的使用