让ng-repeat在AngularJS的$ interpolate服务中工作

时间:2014-01-03 19:24:23

标签: javascript angularjs twitter-bootstrap

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

我在http://plnkr.co/edit/Cuku7qaUTL1lxRkafKzv有一个傻瓜它没有用,因为我不知道如何在plunker中获得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>

1 个答案:

答案 0 :(得分:11)

$interpolate不处理ngRepeat等指令( Difference between parse, interpolate and compile)。 $interpolate

  

将带有标记的字符串编译为插值函数。这个   HTML $编译服务使用服务进行数据绑定。

处理ngRepeat和其他您想要的指令$compile。但是,对于您的用例$compile,遗憾的是会导致许多更改,因为:

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

    这意味着我们需要在您的模板中引用您的属性,例如{{thingy.blah}}而不是{{blah}}。

  • 当弹出窗口在dom上时,需要进行编译。

  • 弹出窗口仅在dom打开时。

因此,我们无法在您的服务中将$interpolate替换为$compile

一种方法是使用以下指令替换data-ng-bind-html,该指令的作用类似于内置ng-bind-html的{​​{1}}(显然,您应该只使用您认为安全的html) )。

$compile

像这样使用(.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> 在范围内。有几种方法可以处理 - 但为了演示目的,我已经手动返回到调用popover的范围 - 这是2个范围,因此是thingy

使用此编译指令,您不再scope.$parent.$parent$interpolate,因此您的服务中的功能可缩小为仅返回相应的模板:

$sanitize

demo fiddle