简体   繁体   English

Angularjs指令,在transcluded内容中包含元素

[英]Angularjs directive with element in the middle of transcluded content

I'm trying to create a splitter directive using angularjs that looks like this: 我正在尝试使用angularjs创建一个splitter指令,如下所示:

<my-splitter>
  <my-pane1>Pane 1</my-pane1>
  <my-pane2>Pane 2</my-pane2>
</my-splitter>

And i want this as a result: 我希望这样做:

<div class="splitter">
  <div class="splitter-pane1">Pane 1</div>
  <div class="splitter-handle"></div>
  <div class="splitter-pane2">Pane 2</div>
</div>

The problem is that I want to put the handler in the middle of the two panes, but i don't know how it can be done using ng-transclude. 问题是我想把处理程序放在两个窗格的中间,但我不知道如何使用ng-transclude来完成它。 Here is the js: 这是js:

angular.module('myModule', [])
    .directive('mySplitter', function() {
        return {
            restrict: 'E',
            replace: true,
            transclude: true,
            template: 'how do i put the handler in the middle of the two panes?'
            ...
        }
    })
    .directive('myPane1', function () {
        return {
            restrict: 'E',
            require: '^mySplitter',
            replace: true,
            transclude: true,
            template: '<div class="split-pane1" ng-transclude><div>'
            ...
        }
    })
    .directive('myPane2', function () {
        return {
            restrict: 'E',
            require: '^mySplitter',
            replace: true,
            transclude: true,
            template: '<div class="split-pane2" ng-transclude><div>'
            ...
        }
    })

Here's one pretty straightforward option, but there are a lot of way you could do it. 这是一个非常简单的选择,但有很多方法可以做到。

I don't think it can be done with templates without making it less dynamic. 我不认为可以使用模板完成而不会降低动态。 In other words, your parent "mySplitter" directive could always create the same markup and it would be fine, but if you want to add more myPane to it, then mySplitter template would have to be changed each time. 换句话说,你的父“mySplitter”指令总是可以创建相同的标记,它会没问题,但是如果你想为它添加更多的myPane ,那么mySplitter都需要更改mySplitter模板。 My solution is simply, easy to read, and dynamic (add as many panes as you want and they will get a divider). 我的解决方案简单,易于阅读和动态(添加任意数量的窗格,他们将得到一个分隔符)。

For the panes, the tricky part is that you seem to want them numbered in the classnames. 对于窗格,棘手的部分是你似乎希望它们在类名中编号。 I don't know why you need that (I doubt you really do), but I included a solution for that. 我不知道为什么你需要那个(我怀疑你真的这么做),但我为此提供了一个解决方案。 You use a variable that each run of the directive can see, but is only initialized once. 您使用指令的每次运行都可以看到的变量,但只初始化一次。 There's a scope that all runs of the directive can see (note where I create the variable count , and then the link function has access to it, but that function runs for each usage of the directive, so each time you can increment it, setting count up for the following directive uses. 有一个范围,指令的所有运行都可以看到(注意我在哪里创建变量count ,然后link函数可以访问它,但该函数运行指令的每次使用,所以每次你可以增加它,设置count以下指令使用。

Live demo here (click). 现场演示(点击)。

var app = angular.module('myApp', []);

app.directive('mySplitter', function($compile) {
  return {
    restrict: 'EA',
    link: function(scope, element, attrs) {
      var children = element.children();
      angular.forEach(children, function(elem, i) {
        if (i < children.length-1) {
          var splitter = angular.element('<div class="splitter-handle">Class is: splitter-handle</div>');
          var child = angular.element(elem);
          child.after(splitter);
        }
      });
    }
  };
});

app.directive('myPane', function() {
  var count = 1; //this runs only once
  return {
    restrict: 'EA',
    transclude: true,
    replace: true,
    scope: {},
    template: '<div class="splitter-pane{{count}}" ng-transclude>Class is: splitter-pane{{count}}</div>',
    link: function(scope, element) { 
      //this runs for each use of "myPane"
      scope.count = count.toString(); //convert to string or there will be an error
      ++count; //increment the count for the next item
    }
  };
});

To clarify what I mean by "dynamic" and "non-dynamic", if you only need two panels divided, you might as well just do this: 为了澄清“动态”和“非动态”的含义,如果你只需要两个面板划分,你可以这样做:

app.directive('mySplitter', function($compile) {
  return {
    restrict: 'EA',
    replace: true,
    template:
      '<div class="splitter">'+
        '<div class="splitter-pane1">Pane 1</div>'+
        '<div class="splitter-handle"></div>'+
        '<div class="splitter-pane2">Pane 2</div>'+
      '</div>'
  };
});

Obviously, the other approach is more flexible. 显然,另一种方法更灵活。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM