如何使指令与父控制器或其兄弟指令

时间:2015-05-15 16:32:37

标签: angularjs angularjs-directive

所有

我是Angular的新手,仍在努力弄清楚所有概念。当我学习设计指令时,有一件事让我困惑:

我想要创建的是一个图像指令(我称之为“imgloader”指令),它具有属性imgurl ,它从父控制器传递(让它成为简单的“主”控制器)目的),当点击此图片时,它将显示自定义样式工具提示以显示其链接。当此指令与ng-repeat一起使用时,所有其他 imgloader 相同imgurl 突出显示其边框,以便用户可以轻松了解有多少图像相同。

结构可能是这样的:

<body ng-controller="main">
    <imgloader ng-repeat="url in imgurls track by $index" imgurl="url"></imgloader>
</body>

imgloader应该是这样的:

<img ng-src="{{imgurl}}" ng-click="showurl_and_hilightother()" />

我正在考虑的imgloader指令是这样的(请修改它以使其正确):

app.directive("imgloader", function(){
    return {
        restrict:"E",
        scope:{imgurl:"="},
        controller: function($scope){ 
            $scope.showurl_and_hilightother = function(){
                // I need to know how to do this
            }
        },
        template: "<img ng-src="{{imgurl}}" ng-click="showurl_and_hilightother()" />"
    }
})

我在想使用$ emit让其他指令知道这个事件,但我不确定这是否是正确的方法(这似乎不是它可能需要$ rootscope或从外部传递的一些参考范围对象),任何人都可以提出任何建议(或代码演示)如何实现这个?

由于

2 个答案:

答案 0 :(得分:1)

如果您希望在父母和指令之间进行通信,可以选择几种方法。如果您在父指令中包含多个指令,并且您想要来回传递信息......我建议继承该父指令控制器,并使用它的数据调用每个指令的控制器

所以给你一些标记

<div ng-controller="mainCtrl">

<parent-directive>
    <child-one-directive></child-one-directive>   
    <child-two-directive></child-two-directive>  
    <child-three-directive-rules-them-all></child-three-directive-rules-them-all>
</parent-directive>

您希望父指令具有每个子节点都可以继承的控制器。

.controller('parentDirectiveController',function($scope) {

$scope.messageFromChildDirective = "some message";

this.updateParentMessage = function(value) {
     $scope.messageFromChildDirective = value;   
}

this.updateParentMessageThenPushToChildren = function(value) {
    $scope.messageFromChildDirective = value;
    $scope.$broadcast("messageChanged",value);
}
})

.directive('parentDirective', function() {

return {
    restrict: 'E',
    transclude: true,
    controller: 'parentDirectiveController',
    link: function(scope,iElement,iAttrs, ctrl) {


        scope.msg = function() {
            scope.messageFromChildDirective = "parent message";
        }


    },
    template: "<div class='parent'>" + "<div ng-transclude></div>" + 
              " <button ng-click='msg()'>Message from parent</button>"+
              "<div>{{messageFromChildDirective}}</div>"+
              "</div>"
}
}) 

上面代码中的重要部分是parentDirective将它的控制器属性设置为&#39; parentDirectiveController&#39;,这是你的其他指令将继承的控制器,所以分配给它的任何东西控制器本身可以通过调用controller.whatever

来访问
.directive('childThreeDirectiveRulesThemAll',function() {
return {
    restrict: 'E',
    require: '^parentDirective',
    link: function(scope,iElement,iAttrs, ctrl) {

        scope.directiveThreeName = 'Child Three Directive';
        scope.$on("messageChanged", handleMessageChanged);
        function handleMessageChanged(eventName, eventData) {
            scope.directiveThreeName = eventData;
        }
        scope.msgFromThree = function() { 
            ctrl.updateParentMessageThenPushToChildren("Child Three Directive") 
        }
    },
    template: "<div class='childThree' ng-click='msgFromThree()'>{{directiveThreeName}}</div>"
}
});

注意在这个指令中,require属性设置为它嵌套在其中的指令的名称。这将继承分配给该指令的控制器。控制器作为指令链接函数的第四个参数传递,并且可以从那里调用附加到该控制器的任何内容。

使用这个范例,正如您在指令中看到的那样,您可以使用某个值调用控制器函数,然后控制器可以广播消息。发出气泡,广播沿着层次结构向下传播,因此只有在控制器范围内创建的范围才能看到广播。可以在任何子指令上监听此广播,以便所有这些指令都可以选择在收到更改通知时进行更新。

我已经组建了一个基本的jsfiddle,它演示了一个用例,其中两个子指令设置了自己的值和父值,但是第三个子指令将一个更改传播给父级以及所有的其他孩子。

我希望这会有所帮助

https://jsfiddle.net/m7urhzbx/

答案 1 :(得分:1)

<div ng-app="mayApp" ng-controller="mayController as ctrl">
    <button may-dve1 dve1="ctrl.pipeline1">Directive 1</button>
    <div may-dve2 dve2="ctrl.pipeline2">Directive 2</div>
</div>

angular.module('mayApp',[])
.controller('mayController',[function(){
    var ctrl=this;
    ctrl.pipeline1={
        do:function(){
            if(ctrl.pipeline2.do instanceof Function)
                ctrl.pipeline2.do();
        }
    };
    ctrl.pipeline2={};
}])
.directive('mayDve1',[function(){
    return {
        scope:{dve1:'='},
        link:function(scope,element){
            element.on('click',function(){
                if(scope.dve1.do instanceof Function)
                    scope.dve1.do();
            });
        }
    }
}])
.directive('mayDve2',[function(){

    return {
        scope:{dve2:'='},
        link:function(scope,element){
            scope.dve2.do=function(){
                element.text('Directive 1 Clicked');
            };
        }
    }
}]);