2014-11-07 4 views
1

Я хотел бы отобразить список объектов с моего контроллера с помощью директивы. Внутри этой директивы я хотел бы использовать одну из нескольких возможных директив, но я не всегда буду знать, какой из них. Если я задал это имя директивы в области контроллера, как я могу использовать его в шаблоне главной директивы?Могу ли я использовать произвольные директивы 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.

В шаблоне prog, я пытаюсь использовать интерполяцию, чтобы вставить имя директивы в скобки. Это, однако, выводит это:

  • < динозавры> Rush
  • < динозавры> King Crimson
  • < динозавры> Porcupine Tree
  • < динозавры> Marillion

Я также пробовал использовать имя класса в span:, и это вставляет «динозавры» в пролет как класс, но Angular не обрабатывает его как директиву.

Я не уверен, нужна ли мне область выделения, но из того, что я прочитал, я не думаю, что это важно. Я также новичок в переходе, но я думаю, что директива dinosaurs должна отображать содержимое каждого элемента списка и добавлять «- ДИНОЗАВРЫ!». до конца.

Какова наилучшая практика перехода от имени одной директивы к другой?

+0

Я смотрел на https://docs.angularjs.org/guide/directive и [посты Dan Wahlin по директивам] (http://weblogs.asp.net/dwahlin/создание пользовательского-angularjs-директивы-часть-2-изолят-сфера). Несколько тем, например [this one] (http://stackoverflow.com/questions/16787276/use-an-angular-directive-inside-another-directive), адресуют директивы внутри других директив, но не передают имена этих директив , –

+0

, если вы сначала объявите директиву динозавров, это поможет? – dandavis

+0

@ dandavis - Приятная мысль, но, видимо, нет. Я попробовал это на plnkr, но не повезло. –

ответ

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>' 
    }; 
}); 
+0

Определенно многообещающий до сих пор - я получил его, чтобы работать в принципе, и просто нужно разработать несколько синтаксис. Благодаря! –

1

Update - У вас есть несколько вариантов в рамках директивы, чтобы изменить шаблон:

Самая простая первая идея: 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(); 
    } 
... 

и аналогичный plunker или plunker

+0

Извините, если мне не хватает чего-то очевидного, но как это помогает? На данный момент у меня нет контроллера на родительском устройстве, хотя, возможно, мне он нужен. Я ищу способы определить childDirective в parentDirective. Если callFunc() позаботится об этом, как шаблон будет использовать его? Спасибо за ответ! –

+0

Возможно, я неправильно понял, потому что лучшая практика для директивы должна быть декларативной, поэтому ' не совсем декларирует много, и я бы сказал, чтобы добавить ваши дочерние элементы в html, но - это больше похоже на ваше намерение заключается в использовании нескольких директив для чередования шаблонов по $ scope.variable в главном контроллере? – Dylan

+0

Да, еще не все, что декларативно - жертва упрощения, я думаю. В самом деле, я использую директиву tree-grid, которая принимает объект с данными и иерархией. В некоторых случаях столбец в сетке должен быть доступен только для чтения со значением, а в других случаях он должен иметь элемент управления для изменения значения. Этот элемент управления для изменения значения - это то, что я пытаюсь вставить в качестве директивы. –

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

+0

Спасибо за ответ. Это свойство TemplateCache довольно круто - я об этом не знал.Если я правильно понял, у этого не было бы вложенных директив вообще, только тот, который делает разные, основывается на свойстве url. Имеет смысл. –

+0

Да - использование $ templateCache в моем примере просто для демонстрации использования разных файлов шаблонов внутри jsbin. В реальном приложении вам, скорее всего, понадобятся отдельные файлы шаблонов. – jelbourn

Смежные вопросы