我可以在其他指令中使用任意AngularJS指令吗?

时间:2014-11-07 20:13:30

标签: javascript angularjs

我想使用指令显示控制器中的对象列表。在该指令中,我希望能够使用几种可能的指令中的一种,但我不会总是知道哪一种。如果我在控制器的范围内设置该指令名称,我如何在主指令的模板中使用它?

这里有plnkr以及下面的内容。

HTML:

<div ng-app="music" ng-controller="rock">
  <h1>Favorite Bands</h1>
  <prog></prog>
</div>

JS:

angular.module('music', []);

angular.module('music').controller('rock', ['$scope', function($scope){
  $scope.directiveName = 'dinosaurs';
  $scope.bands = [
    { name:'Rush'}, { name:'King Crimson' }, { name: 'Porcupine Tree'}, { name: 'Marillion'}];
}]);

angular.module('music').directive('prog', function(){
  return {
    restrict: 'E',
    replace: true,
    template: '<ul><li ng-repeat="band in bands"><{{directiveName}}>{{band.name}}</{{directiveName}}></li></ul>'
  };
});

angular.module('music').directive('dinosaurs', function(){
  return {
    restrict: 'E',
    transclude: true,
    template: '<ng-transclude></ngtransclude> - DINOSAUR!'
  };
});

在这种情况下,我将$scope.directiveName设置为dinosaurs,这是我想在主要指令中使用的指令的名称,称为prog。< / p>

prog的模板中,我尝试使用插值将指令的名称插入括号中。但是,这会输出:

  • &LT;恐龙&GT;拉什
  • &lt; dinosaurs&gt; King Crimson
  • &lt; dinosaurs&gt; Porcupine Tree
  • &LT;恐龙&GT;马里利恩

我还尝试在跨度上使用类名:,并插入&#34;恐龙&#34;作为一个类进入跨度,但Angular不会将其作为指令处理。

我不确定我是否需要一个隔离范围,但从我所读过的内容来看,我并不认为这是相关的。我也是翻译新手,但我认为dinosaurs指令应该采用每个列表项的内容并添加&#34; - DINOSAURS!&#34;到最后。

将一个指令的名称传递给另一个指令的最佳做法是什么?

3 个答案:

答案 0 :(得分:1)

我要做的是避免凌乱的$compile s使用ng-include作为切换,例如this

angular.module('music').directive('prog', function(){
  return {
    restrict: 'E',
    replace: true,
    template: '<ul><li ng-repeat="band in bands"><div ng-include="directiveName + \'.html\'"></div></li></ul>'
  };
});

答案 1 :(得分:1)

更新 - 您可以在指令中使用一些选项来更改模板:

最简单的第一个想法是template:function(el, attr),它允许您返回一个功能,使您可以根据non-interpolated属性更改模板。所以它可能无法满足您的需求。

template:function() plunker

另一种方法是$编译模板并替换链接函数中的元素。

$compile plunker


这不是关于多模板的 -

您可以在链接功能中访问父指令的控制器并在其中维护范围。 这里试图将其简化为基本要素:

app.directive("parentDirective", function() {
  return {
    restrict: 'EA',
    controller: function($scope) {
        this.callFunc = function(){
           ...
        }
    }
  }
});

app.directive("childDirective", function($compile, $log) {

  return {
    require: '?^parentDirective',
    scope: {
       model: '=ngModel'
    },
    link : function(scope, el, attr, ctrl) {
        ctrl.callFunc();
    }
...

和类似的plunkerplunker

答案 2 :(得分:1)

一种可能的解决方案是将“如何渲染此项目”的责任从控制器/指令转移到项目本身。

最简单的方法是给项目一个templateUrl属性。然后,您可以引入一个简单的包装器指令来绑定项目:

myModule.directive('bandView', function() {
  return {
    scope: {band: '=bandView'}
    templateUrl: '<div ng-include="band.templateUrl"></div>'
  };
});

然后,如果你有一些乐队列表,你可以渲染它们:

<h1>My band list</h1>
<div ng-repeat="b in bands" band-view="b"></div>

然后,您将为每种类型的渲染设置不同的html模板。

以下是运行的想法:http://jsbin.com/EhAnIMaJ/2/edit?html,js,output