本篇介紹指令的最后兩個屬性,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
