在ng-repeat中包含不同的角度指令

时间:2016-05-18 13:52:16

标签: angularjs angularjs-directive angularjs-ng-repeat

我有几个角度指示 我想根据类型将它们包含在带有ng-repeat的手风琴指令中 我希望它可以重复使用,所以我不希望手风琴知道它所呈现的指令类型。
这就是为什么我不想在手风琴中使用ng-switch指令的原因。 这是一个非常简化的演示。实际上,这些指令将具有自己的角度来编译。



var testApp = angular.module('testApp', []);
(function() {
  function Element1() {
    return {
      template: '<span>hello</span>',
      restrict: 'E',
      replace: true
    }
  }
  testApp.directive('elementOne', Element1);
}());

(function() {
  function Element2() {
    return {
      template: '<span>world</span>',
      restrict: 'E',
      replace: true
    }
  }
  testApp.directive('elementTwo', Element2);
}());

(function() {
  function Accordion() {
    return {
      template: '<ul><li ng-repeat="element in elements"><button>Toggle</button> Here should be the directive</li></ul>',
      restrict: 'E',
      replace: true,
      controller: function($scope) {
        $scope.elements = [{
          type: 1
        }, {
          type: 2
        }];
      }
    }
  }
  testApp.directive('elementAccordion', Accordion);
}());
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="testApp">
  <element-accordion></element-accordion>
</div>
&#13;
&#13;
&#13;

谢谢!

1 个答案:

答案 0 :(得分:1)

几周前,我已经建立了非常相似的东西。我想渲染一个指令列表,并根据数组中元素的类型选择指令类型(就像你一样)。我试图避免使用ngSwitch,因为我有很多指令,并希望每次都不添加ngSwitch语句而添加新指令。让我展示一下我所做的简化版本。我希望这可以帮助您构建自己的版本。

首先,我们需要一个element diretives的全局目录和一个帮助函数来注册新的指令。在我的情况下,帮助函数甚至创建指令,但我会跳过这个以保持简单:

angular.module("app").provider('elementDirectory', function() {        
  return {
    elements: [],
    $get: function () {
      return {
        elements: this.elements
      }
    }
  };
});

function registerElementDirective(type, directiveName) {
  angular.module("app").config(['elementDirectoryProvider', function (elementDirectoryProvider) {
    elementDirectoryProvider.elements.push({
      type : type,
      directive : directiveName
    });
  }]);
}

现在,我们可以创建一些这样的指令:

angular.module("app").directive('elementA', function() {
    return {
      template: '<span>ElementA</span>',
    }
});
registerElementDirective('A', 'element-a');

最有趣的部分是我称之为elementSwitch的指令。它需要一个元素数组,并为每个元素动态添加angular.element。因此,它为elementDirectoy中的每个元素创建原型,并在更改时使用clone()方法。 (我想我们可以跳过这部分,这是一个优化)。

angular.module('app').directive('elementSwitch', elementSwitch);    
elementSwitch.$inject = ['$compile', 'elementDirectory'];
function elementSwitch($compile, elementDirectory) {

  var prototypes = {};
  elementDirectory.elements.forEach(function (e) {
    var directiveElem = angular.element('<' + e.directive + '>');
    prototypes[e.type] = directiveElem;
  });

  return {
    scope: {
      elements: '=elementSwitch'
    },
    link: function (scope, elem, attr) {

      var childScopes = [];
      scope.$watchCollection('elements', function (newValue, oldValue) {
        childScopes.forEach(function (s) {
          s.$destroy();
        });
        childScopes = [];
        elem.empty();

        newValue.forEach(function (element, index) {
          var childScope = scope.$new();
          childScopes.push(childScope);
          var directiveElem = prototypes[element].clone();
          directiveElem.attr('element', '_elements[' + index + ']');
          $compile(directiveElem)(childScope);
          elem.append(directiveElem);
        });
        scope._elements = newValue;
      });
    }
  }
}

以下是一个完整的示例:https://codepen.io/hansmaad/pen/oLvRmj

它不会做你想要的同样的事情,但是你应该知道如何实现你的目标。