angular.module('dragModule', []). directive('myDraggable', function($document) { return function(scope, element, attr) { var startX = 0, startY = 0, x = 0, y = 0; element.css({ position: 'relative', border: '1px solid red', backgroundColor: 'lightgrey', cursor: 'pointer' }); element.on('mousedown', function(event) { // Prevent default dragging of selected content event.preventDefault(); startX = event.screenX - x; startY = event.screenY - y; $document.on('mousemove', mousemove); $document.on('mouseup', mouseup); }); function mousemove(event) { y = event.screenY - startY; x = event.screenX - startX; element.css({ top: y + 'px', left: x + 'px' }); } function mouseup() { $document.unbind('mousemove', mousemove); $document.unbind('mouseup', mouseup); } } });
创建相互通信的指令
你可以通过在模板使用指令来组合任何指令。
有时候,你想要一个指令从其他的指令上面创建
想象你想要一个带有tab的容器,容器的内容对应于激活的tab。
<my-tabs> <my-pane title="Hello"> <h5>Hello</h5> <p>Lorem ipsum dolor sit amet</p> </my-pane> <my-pane title="World"> <h5>World</h5> <em>Mauris elementum elementum enim at suscipit.</em> <p><a href ng-click="i = i + 1">counter: {{i || 0}}</a></p> </my-pane> </my-tabs>
JS
angular.module('docsTabsExample', []) .directive('myTabs', function() { return { restrict: 'E', transclude: true, scope: {}, controller: function($scope) { var panes = $scope.panes = []; $scope.select = function(pane) { angular.forEach(panes, function(pane) { pane.selected = false; }); pane.selected = true; }; this.addPane = function(pane) { if (panes.length == 0) { $scope.select(pane); } panes.push(pane); }; }, templateUrl: 'my-tabs.html' }; }) .directive('myPane', function() { return { require: '^myTabs', restrict: 'E', transclude: true, scope: { title: '@' }, link: function(scope, element, attrs, tabsCtrl) { tabsCtrl.addPane(scope); }, templateUrl: 'my-pane.html' }; });
my-tabs.html
<div> <ul> <li ng-repeat="pane in panes" ng-class="{active:pane.selected}"> <a href="" ng-click="select(pane)">{{pane.title}}</a> </li> </ul> <div ng-transclude></div> </div>
my-pane.html
<div ng-show="selected" ng-transclude> </div>
myPane指令有一个require:'^myTabs'的配置,当指令使用这个配置,$compile服务叫myTabs的指令并获取它的控制器实例,如果没有找到,将会抛出一个错误。'^'前缀意味着指令在它的父元素上面搜索控制器(没有'^'前缀的话,指令默认会在自身的元素上面搜索指定的指令)。
这里myTabs的控制器是来自何处呢?通过使用controller配置可以为指令指定一个控制器, 上问例子中myTab就是使用这个配置。就像ngController, 这个配置为指令的模板绑定了一个控制器。
再看我们的myPane's定义,注意到link函数的最后一个参数: tabCtrl,当一个指令包含另一个指令(通过require方式),它会接收该指令的控制器实例作为link函数的第四个参数,利用这个,myPane可以调用myTabs的addPane函数。
精明的读者可能想知道link跟controller之间的区别,最基本的区别就是控制器开放一个API(就是这个控制器实例可以被其他实例读取到),link函数可以通过require与控制器交互。
Best Practice: 当你要开放一个API给其他指令的时候使用控制器,否则使用link函数。
总结
这里我们讲解了一个些指令的主要使用案例。每一个都可以作为你创建自己指令的很好的起点。