【问题标题】:AngularJS : ng-transclude in directive and sending events to parentAngularJS:指令中的 ng-transclude 并向父级发送事件
【发布时间】:2014-02-01 18:20:17
【问题描述】:

我有这样的自定义指令:

<fold fold-name="Musique et sons">
    <sound-button height=60  song-name="Why Make..."></sound-button>
</fold>

fold 指令有这样的模板:

<button class="fold" ng-click="showMe = !showMe">{{foldName}} ({{nb}})</button>
<div class="fold" ng-transclude ng-show="showMe"></div>

在声音按钮控制器中,我必须这样做:

$scope.$parent.$$prevSibling.$emit('foldstop')

如果我希望控制器接收事件:

      $scope.$on 'foldplay', (sender, evt) ->

发生了什么: 创建 3 个作用域:

 <fold> Scope
 <ng-transclude scope> which has no model, thus no controller.
      <sound-button scope> 

在 sound-button 指令中,$scope.$emit 会命中 ng-transclude 范围,它是我想要命中的范围的兄弟。

所以我使用 $scope.$parent.$prevSibling 来点击正确的控制器。 可以,但是有更好的方法吗?

谢谢!

【问题讨论】:

  • 我有点困惑。如果你想在折叠里面做东西。您可以在折叠中创建一个控制器,并在需要时从声音按钮调用它。

标签: angularjs transclusion


【解决方案1】:

如果你的指令相关,你可以试试require

app.directive('soundButton', function() {
    return {
      restrict: 'E',
      scope: {
        songName: '@'
      },
      require:"^fold", 
      link : function (scope,element,attrs,foldController){//inject fold controller 
           foldController.callFold("message"); //use the controller to communicate
      }
    };
});

app.directive('fold', function() {
    return {
      restrict: 'E',
      scope: {
        foldName: '@'
      },
      templateUrl: 'fold.html',
      transclude:true,

      controller:function(){ //declare the controller to be used by child directives.
          this.callFold = function (message){
            alert(message);
          }
      }
    };
});

DEMO

您不能使用$scope.$emit,因为您的指令范围没有父/子关系。您可以参考this discussion了解更多信息。

更新:

如果您的指令不相关并且您需要有父/子关系,您可以尝试自定义嵌入:

app.directive('fold', function() {
    return {
      restrict: 'E',
      scope: {
        foldName: '@'
      },
      templateUrl: 'fold.html',
      transclude:true,

      compile: function (element, attr, linker) {
          return {
           pre: function (scope, element, attr) {
             linker(scope, function(clone){ //bind the scope your self
                 element.children().eq(1).append(clone); // add to DOM
             });
           },
           post: function postLink(scope, iElement, iAttrs) {  
               scope.$on("foldplay",function(event,data){
                 alert(data);
               });
            }
          };
      }
    };
});

DEMO(点击按钮,然后点击显示的文字)

【讨论】:

  • 谢谢,但在我的情况下,有时声音按钮没有父折叠...此外,折叠可以嵌套,并且还应该注意顶部的折叠,这就是我需要 $emit 的原因。跨度>
  • @user2944669:我添加了 1 个自定义嵌入的解决方案
  • 非常聪明!在您的提议和我的提议之间(将所有内容都留在控制器中,但以我称之为发出 $scope.$parent.$prevSibling 的方式作弊),优缺点是什么?
  • @user2944669:这是为了改变 Angular 创建范围层次结构的默认方式。很抱歉,我不知道为什么 Angular 会这样做
  • 是的,我不知道为什么 ng-transclude 创建这个同级作用域。比其他任何事情都令人烦恼!
猜你喜欢
  • 2015-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-21
  • 1970-01-01
  • 2019-02-22
相关资源
最近更新 更多