@@ -659,4 +659,132 @@ Table 6-6. Angular specific functions on an element
659
659
660
660
.closed {
661
661
display: none;
662
- }
662
+ }
663
+
664
+ ###控制器
665
+
666
+ 当你有相互嵌套的指令需要相互通信时, 你可以通过控制器做到这一点. 比如一个\< menu\> 可能需要知道它自身内部的\< menu-item\> 元素它才能适当的显示或者隐藏它们. 同样的对于一个\< tab-set\> 也需要知道它的\< tab\> 元素, 或者一个\< grid-view\> 要知道它的\< grid-element\> 元素.
667
+
668
+ 正如前面所展示的, 创建一个API用于在指令之间沟通, 你可以使用控制器属性的语法声明一个控制器作为一个指令的一部分:
669
+
670
+ controller: function controllerConstructor($scope, $element, $attrs, $transclude)
671
+
672
+ 这个控制器函数就是依赖注入, 因此这里列出的参数都是潜在的可用并且全部都是可选的--它们可以按照任意顺序列出. 它们也仅仅只是可用服务的一个子集.
673
+
674
+ 其他的指令也可以使用` require ` 属性语法将这个控制器传递给它们. 完整的` require ` 的形式看起来像:
675
+
676
+ require: '^?directiveName'
677
+
678
+ 关于` require ` 字符串参数的说明可以在表6-7中找到.
679
+
680
+ Table 6-7. Options for required controllers
681
+
682
+ <table >
683
+ <thead>
684
+ <tr>
685
+ <th>Option</th>
686
+ <th>Usage</th>
687
+ </tr>
688
+ </thead>
689
+ <tbody>
690
+ <tr>
691
+ <td>directiveName</td>
692
+ <td>这个指令驼峰式命名规范应该是来自于控制器. 因此如果我们的\<my-menu-item\>s指令需要在它的父元素\<my-menu\>上找到一个控制器, 我们需要将它编写为`myMenu`.</td>
693
+ </tr>
694
+ <tr>
695
+ <td>^</td>
696
+ <td>默认情况下, Angular会从同一元素的命名指令中获取控制器. 加入可选的^符号表示总是遍历DOM树来以查找指令. 对于\<my-menu\>示例, 我们需要添加这个符号; 最终的字符就是`\^myMenu`.</td>
697
+ </tr>
698
+ <tr>
699
+ <td>?</td>
700
+ <td>如果你所需要的控制器没有找到, Angular将抛出一个异常信息来告诉你遇到了什么问题. 添加一个?符号给字符串就是说这个控制器时可选的并且如果没有找到控制器它不应该抛出一个异常. 虽然者听起来不可能, 但是如果我们希望让\<my-menu-item\>不需要使用一个\<my-menu\>容器, 我们可以将这个添加给最终所需要的字符串?\^myMenu.</td>
701
+ </tr>
702
+ </tbody>
703
+ </table >
704
+
705
+ 例如, 让我们重写我们的expander指令用于一组称为"手风琴"的组件, 它可以确保当你打开一个expander时, 其他的都会自动关闭. 它看起来如图6-4所示.
706
+
707
+ ![ 6-4] ( figure/accordion.png )
708
+
709
+ 图 6-4. Accordion component in multiple states
710
+
711
+ 首先, 让我们编写处理手风琴菜单的accordion指令. 这里我们将添加我们的控制器构造器方法来处理手风琴:
712
+
713
+ appModule.directive('accordion', function() {
714
+ return {
715
+ restrict: 'EA',
716
+ replace: true,
717
+ transclude: true,
718
+ template: '<div ng-transclude></div>',
719
+ controller: function() {
720
+ var expanders = [];
721
+ this.gotOpened = function(selectdExpander) {
722
+ angular.forEach(expanders, function(expander){
723
+ if(selectedExpander != expander) {
724
+ expander.showMe = false;
725
+ }
726
+ });
727
+ }
728
+
729
+ this.addExpander = function(expander) {
730
+ expanders.push(expander);
731
+ }
732
+ }
733
+ }
734
+ });
735
+
736
+ 这里我们定义了一个` addExpander() ` 函数给expanders便于调用它来注册自身实例. 我们也创建了一个` gotOpened() ` 函数给expanders便于调用, 因而让accordion的控制器可以知道它能够去关闭任何其他展开的expanders.
737
+
738
+ 在expander指令自身中, 我们将从它的父元素扩展它所需要的accordion控制器并在适当的时间里调用` addExpander() ` 和` gotOpened() ` 方法.
739
+
740
+ appModule.directive('expander', function(){
741
+ return {
742
+ restrict: 'EA',
743
+ replace: true,
744
+ transclude: true,
745
+ require: '^?accordion',
746
+ scope: { title: '=expanderTitle' }
747
+ template: '<div>' +
748
+ '<div class="title" ng-click="toggle()">{{title}}</div>' +
749
+ '<div class="body" ng-show="showMe" ng-transclude></div>' +
750
+ '</div>',
751
+ link: function(scope, element, attrs, accordionController) {
752
+ scope.showMe = false;
753
+ accordionController.addExpander(scope);
754
+
755
+ scope.toggle = function toggle() {
756
+ scope.showMe = !scope.showMe;
757
+ accordionController.gotOpened(scope);
758
+ }
759
+ }
760
+ }
761
+ });
762
+
763
+ 注意在手风琴指令的控制器中我们创建了一个API, 通过它可以让expander可以相互通信.
764
+
765
+ 然后我们可以编写一个模板来使用这些指令, 最后生成的结果整如图6-4所示.
766
+
767
+ <body ng-controller="SomeController">
768
+ <accordion>
769
+ <expander class="expander" ng-repeat="expander in expanders" expander-title="expander.title">
770
+ {{expander.text}}
771
+ </expander>
772
+ </accordion>
773
+ </body>
774
+
775
+ 当然接下是对应的控制器:
776
+
777
+ function SomeController($scope){
778
+ $scope.expanders = [
779
+ {title: 'Click me to expand',
780
+ text: 'Hi there folks, I am the content that was hidden but is now shown.'},
781
+ {title: 'Click this',
782
+ text: 'I am even better text than you have seen previously'},
783
+ {title: 'No, click me!',
784
+ text: 'I am text should be seen before seeing other texts'}
785
+ ];
786
+ }
787
+
788
+ ##小结
789
+
790
+ 正如我们所看到的, 指令允许我们扩展HTML的语法并让很多应用程序按照我们声明的意思工作. 指令使重用(代码重用/组件复用)变得轻而易举--从使用` ng-model ` 和` ng-controller ` 配置你的应用程序, 到处理模板的任务的像` ng-repeat ` 和` ng-view ` 指令, 再到前几年被限制的可复用的组件像数据栅格, 饼图, 工具提示和选项卡等等.
0 commit comments