Включенный контент неправильно компилируется

Мне нужно, чтобы перекомпилированный контент моей директивы перекомпилировался при изменении атрибута в родительской области, а затем получил весь скомпилированный HTML.

Вот директива:

<custom-directive title="bla">
  <!--
   Here I iterate over the parent scope's logs variable;
   Nothing stays as result of the compilation
  -->
  <span ng-repeat="log in logs">{{ log }}</span>

 <!-- Expressions like these are evaluated fine when using $interpolate -->
 {{ 'foo' }}
</custom-directive>

Вот реализация директивы:

{
  template: '<a class="btn">Do something</a>',
  replace: true,
  restrict: 'E',
  transclude: true,
  scope: {
    title: '@'
  },
  link: function (scope, element, attrs, ctrl, transclude) {
    scope.$watch(function () {
      return scope.$parent.logs;
    }, function () {
      transclude(function (clone) {
        $compile(clone)(scope.$parent);

        // Now I need to use the compiled clone from here,
        // turn it into plain text and URL encode it
      });
    }, true);
  }
};

Проблема в том, что любые директивы, которые я использую в включенном HTML (т.е. в теле директивы), не оцениваются, например, ngRepeat. Если я использую $interpolate вместо $compile в функции ссылки, по крайней мере, выражения в {{ }} печатаются правильно, но мне нужно, чтобы весь включенный HTML был правильно скомпилирован.

Другими словами, моя цель состоит в том, чтобы перекомпилировать HTML внутри директивы каждый раз, когда изменяются журналы родительской области, а затем захватить этот скомпилированный HTML и делать с ним что-то (мне нужно в конечном итоге превратить его в обычный текст и закодировать его URL).

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


person weltschmerz    schedule 16.09.2015    source источник
comment
Возможно, предоставить JSFiddle?   -  person Joy    schedule 17.09.2015


Ответы (1)


Я понял. Я, вероятно, просто не совсем понимаю функцию transclude, которую я могу передать своему методу ссылки; ручная компиляция просто не сделала этого для меня.

Вместо этого я включил директиву ngTransclude в шаблон директивы. Таким образом, включенный контент является частью element внутри функции ссылки и автоматически корректно компилируется.

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

Мораль этой истории: не связывайтесь с функцией transclude, просто используйте ngTransclude внутри шаблона и получите к ней доступ на самом element.

{
  template: '<a class="btn">Do something <div ng-transclude class="hidden"></div></a>',
  replace: true,
  restrict: 'E',
  transclude: true,
  scope: {
    title: '@'
  },
  link: function (scope, element, attrs, ctrl, transclude) {
    scope.$watch(function () {
      return element.find('[ng-transclude]').text();
    }, function (text) {
      // do something with text here
    }, true);
  }
};
person weltschmerz    schedule 17.09.2015