我正在将AngularJs-UI组件用于Bootstrap。我想将填充的模板插入到弹出功能的数据元素之一中。这适用于所有不在ng-repeat内的元素。如何使ng-repeat元素在插值模板内工作?

我在http://plnkr.co/edit/Cuku7qaUTL1lxRkafKzv处有一个插件,它不起作用,因为我不知道如何在插件中获取Angular-UI-bootstrap。

<div data-popover="{{createHTML()}}">some content</div>

我的本地作用域具有createHTML()函数,看起来像这样。
angular.module('myApp', ['ngSanitize'])
  .controller("myController", function(myService){
    $scope.createHTML = function() {
      var thingy = { blah: "foobar", collection: [ "1", "2", "3" ] };
      return myService.html_for(thingy);
    }
  });

服务是
angular.module('myApp')
  .service('myService', function($templateCache, $interpolate, $sanitize, $log) {
    "use strict";

    function html_for(thingy) {
      var template = $templateCache.get('thingyTemplate.html'),
        link = $interpolate(template),
        html = link(thingy),
        unsafe = $sanitize(html);
      return unsafe;
    }

    return {
      html_for: html_for
    }
  });

范本:
<script type="text/ng-template" id="thingyTemplate.html">
  <div>
    <div><strong>Blah:</strong> {{blah}}</div>
    <div data-ng-repeat="foo in collection"><strong>Collection:</strong> {{foo}}</div>
    <div><strong>Collection[0]:</strong> {{collection[0]}}</div>
    <div><strong>Collection[1]:</strong> {{collection[1]}}</div>
    <div><strong>Collection[2]:</strong> {{collection[2]}}</div>
  </div>
</script>

<script type="text/ng-template" id="template/popover/popover.html">
<div class="popover {{placement}}" data-ng-class="{ in: isOpen(), fade: animation() }">
  <div class="arrow"></div>

  <div class="popover-inner">
    <h3 class="popover-title" data-ng-bind="title" data-ng-show="title"></h3>
    <div class="popover-content" data-ng-bind-html="content"></div>
  </div>
</div>
</script>

最佳答案

$interpolate不处理ngRepeat(
Difference between parse, interpolate and compile)。 $interpolate :



要处理ngRepeat和其他指令,您需要 $compile 。但是不幸的是,对于您的用例,$compile将导致许多更改,因为:

  • 它需要一个编译范围,而不是像$interpolate这样的上下文。此外,还需要打开thingy范围。

    这意味着我们将需要像{{thingy.blah}}这样引用您的属性,而不是模板中的{{blah}}。
  • 当弹出窗口位于dom上时,需要进行编译。
  • 弹出窗口仅在打开时才在dom上。

  • 因此,我们不能只在您的服务中用$interpolate替换$compile

    一种方法是用以下指令替换data-ng-bind-html,该指令的行为类似于内置ng-bind-html$compile(显然,您应该仅将它与知道安全的html一起使用)。
    .directive('compile', function($compile) {
      return function(scope, element, attrs) {
        scope.$watch(
          function(scope) {
            return scope.$eval(attrs.compile);
          },
          function(value) {
            var result = element.html(value);
            $compile(element.contents())(scope.$parent.$parent);
          }
        );
      };
    });
    

    像这样使用(用compile代替ng-bind-html:
      <div class="popover-content" compile="content"></div>
    

    一个问题是我们需要thingy在范围内。有几种方法可以处理该问题,但是出于演示目的,我手动回到了弹出窗口的作用域from,这是2个作用域,即scope.$parent.$parent

    使用此编译指令,您不再需要$interpolate$sanitize,因此服务中的函数可以缩小为仅返回适当的模板:
    function html_for() {
      var template = $templateCache.get('thingyTemplate.html');
      return template;
    }
    

    demo fiddle

    08-18 04:52