2014-04-07 52 views
5

我试图在父指令和它的嵌套子指令之间进行通信,而另一种方式。我已经设法通过使用$ broadcast和$ emit来实现此目的,但是因为我将一些参数传递给了指令,所以我必须在指令上创建隔离范围,因此为了让$ broadcast/$ emit我必须在父范围(范围:$ parent。$ broadcast)上播出'上一级'。 现在广播不再只是去嵌套的孩子,而是去了同一级别的所有指令,这是我不想要的。我创建了一个潜水员来显示问题,here。 我需要的是当按下其中一个按钮时,只有子指令才能接收广播消息,反之亦然。我是否错过了某些东西,或者在使用隔离范围时不可行?嵌套指令之间的通信

在我的HTML:

<body ng-app="myApp"> 
    <directive1 data-title="Click me to change name"> 
    <directive2 data-name="John Smith"></directive2> 
    </directive1> 

    <directive1 data-title="Click me to change this other name"> 
    <directive2 data-name="Gordon Freeman"></directive2> 
    </directive1> 
</body> 

指令1:

<div> 
    <button ng-click="changeName()">{{title}}</button> 
    <div ng-transclude></div> 
</div> 

指令2:

<div> 
    <h2>{{name}}</h2> 
</div> 

我的指令:

myApp.directive('directive1', function(){ 
    return { 
    restrict: 'E', 
    replace: true, 
    templateUrl: 'Directive1.html', 
    transclude: true, 
    scope: { 
     title: '@' 
    }, 
    link: function(scope, elem){ 
     scope.changeName = function() { 
     scope.$parent.$broadcast('ChangeName'); 
     }; 

     scope.$parent.$on('NameChanged', function(event, args){ 
     scope.title = 'Name changed to ' + args; 
     }); 
    } 
    } 
}); 


myApp.directive('directive2', function(){ 
    return { 
    restrict: 'E', 
    replace: true, 
    templateUrl: 'Directive2.html', 
    scope: { 
     name: '@' 
    }, 
    link: function(scope, elem){ 
     scope.$on('ChangeName', function(event, args){ 
     scope.name = 'Adam West'; 

     scope.$emit('NameChanged', 'Adam West'); 
     }); 
    } 
    } 
}); 
+1

这里看看http://programmers.stackexchange.com/questions/223006/communication-between-nested-directives – user902383

+0

谢谢,但我不认为任何的是适用于此处;我不想注入一个服务(似乎矫枉过正)。需要父指令不起作用(我假定是因为使用了transclude),并且在父范围中执行表达式(通过&)将会工作,但只有一种方法(父指令的嵌套指令执行函数)。 –

+1

你有没有考虑设置id的指令,然后只有内部指令持有相同的id作为外部指令将处理事件。看看这个例子http://plnkr.co/edit/dqGPDMF3f8NLBH4GX6dO?p=preview – user902383

回答

4

指令之间有5种主要的通信方式:

1)通用服务。

这不是一个很好的解决方案,因为服务总是单例,并且你想要有多个独特的指令。如果您在服务中维护父母和子女的字典,并且将呼叫路由到正确的关联父/子,这与您使用事件的问题相同,则只能使用服务。

2)活动。

如果您无法通过从正确的节点进行广播将事件限制到DOM /树的正确部分,则必须为事件添加唯一标识符。在这种情况下,如果您正在从根和/或多个孩子接收信息进行广播,请给每个父母/孩子一个唯一的标识符并将其添加到emit/broadcast/on。这不是一个漂亮的解决方案,但它会起作用。

3)单向绑定。

'&'绑定在一个独立的作用域中可让您将父函数传递给子对象。然后孩子可以在父范围上调用这些函数来通知父母的变化。这对孩子与家长之间的沟通很有帮助,但不会以其他方式进行。您可以将此解决方案与来自家长的事件进行广播,以便与孩子沟通。

4)双向绑定。

有时,您可以使用隔离作用域上的属性来传递信息或标志以及在父子之间。这在你的例子中不起作用,因为父母不知道他的孩子的任何事情,因为孩子是通过跨越式注入的。

5)require父控制器。

指令可以使用require属性来指定另一个指令需要作为父项还是同一个元素存在。你不能要求兄弟指令。所需的指令必须定义控制器。控制器然后传递给链接(或编译)功能,您可以调用控制器上的功能。这可以用来允许指令之间的通信。在你的例子中,如果指令2需要指令1,你可以给控制器设置如addChild()这样的函数。然后,孩子(指令2)将自己添加到可以在调用changeName时更新/调用所有孩子的父母身上。

myApp.directive('directive1', function(){ 
    return { 
    // ... 
    controller: function($scope) { 
     $scope.children = []; 
     this.addChild = function(child) { 
     $scope.children.push(child); 
     } 
    }, 
    link: function(scope, elem){ 
     scope.changeName = function() { 
     _.each(scope.children, function(child) { 
      child.setName('Adam West'); 
     }; 
     }; 
    }, 
    } 
}); 


myApp.directive('directive2', function(){ 
    return { 
    // ... 
    require: "^directive1", // require directive1 as a parent or on same element 
    link: function(scope, elem, attributes, directive1Controller){ 
     child = { 
     setName: function(name) { 
      scope.name = name; 
     }, 
     }; 

     directive1Controller.addChild(child); 
    } 
    } 
});