Можно ли условно применить транслюцию к директиве?

#angularjs

#angularjs

Вопрос:

Можно ли решить, применять ли преобразование к элементу на основе переменной области видимости?

Например (глупый упрощенный сокращенный пример того, чего я пытаюсь достичь)

 app.directive('myHighlight', function () { 
  return {
    transclude : true,
    template : "<div style='border:1px solid red'><span ng-transclude></span></div>"
  }
});

app.directive('myDirective', function () { 
  return { 
    template : "<span>some text</span>",
    link : function (scope,element,attr) { 
        if ( 'shouldHighlight' in attr) {
          // wrap this directive with my-highlight
        }
    }
  }
});
  

А затем в html

 <span my-directive></span>
<span my-directive should-highlight></span>
  

Примечание, пожалуйста, не говорите мне просто добавить выделение вместо should-highlight, как я уже сказал, это глупый сокращенный пример. Спасибо.

Ответ №1:

Вместо того, чтобы необязательно применять директиву выделения, всегда применяйте ее и выполняйте необязательный перенос внутри этой директивы. Необязательный перенос достигается с ng-if помощью и логического значения, передаваемого из myDirective в myHighlight через разметку:

<div my-highlight="someBooleanValue">some text</div>

Шаблон myHighlight :

 <div ng-if="actuallyTransclude" style="border:1px solid red">
    <span ng-transclude></span>
</div>
<div ng-if="!actuallyTransclude" ng-transclude></div>
  

Рабочий jsfiddle: http://jsfiddle.net/wilsonjonash/X6eB5 /

Комментарии:

1. Спасибо за совет, но моя проблема в том, что переданная директива передается как метаданные, поэтому я пытаюсь найти способ ввести ее по имени (аналогично службе $controller). Мне нужно условно применить разные транслюдированные директивы к разным шаблонам.

2. ах, хорошо. как насчет того, чтобы проголосовать за усилия? 😉

Ответ №2:

Конечно. Когда вы указываете параметр transclude, вы знаете, что можете декларативно указать, куда должен идти контент, используя ng-transclude .

В функции связывания директивы вы также получите ссылку на функцию преобразования (https://docs.angularjs.org/api/ng/service /$compile, см. раздел ссылки):

 function link(scope, iElement, iAttrs, controller, transcludeFn) { ... }
  

transcludeFn вернет переведенное содержимое, поэтому вы можете условно вставлять то, что было и когда вы хотите, в функцию ссылки вашей директивы.

Пример (http://jsfiddle.net/DKLY9/22 /)

HTML

 <parentdir flg="1">
    Child Content
</parentdir>
  

JS

 app.directive('parentdir', function(){
    return {
        restrict : 'AE',
        scope: {
            flg : "="
        },
        transclude : true,
        template : "<div>Parent {{childContent}} Content</div>",
        link : function(scope, elem, attr, ctrl, transcludeFn){
            if (scope.flg==1){ 
                scope.childContent="Include Me instead";
            } 
            else {
                scope.childContent = transcludeFn()[0].textContent; 
            }
      }
    }
});
  

Это упрощенный пример. Чтобы получить лучшее представление о том, как использовать функцию transclude, обратитесь к следующему: http://blog.omkarpatil.com/2012/11/transclude-in-angularjs.html

Ответ №3:

Когда я подхожу к такого рода проблемам, я просто смотрю на то, что сделал angular. Обычно их исходный код очень удобочитаем и прост в повторном использовании. ngTransclude ничем не отличается:

https://github.com/angular/angular.js/blob/master/src/ng/directive/ngTransclude.js

Остальное я оставляю вам. Вы можете либо создать свою собственную директиву преобразования, которая также получает условие, либо просто дублировать код в вашу конкретную директиву, когда условие if имеет значение true.

Если у вас все еще есть проблемы, пожалуйста, дайте мне знать, и мы настроим plunker.