【问题标题】:Getting ng-repeat to work inside of AngularJS's $interpolate service让 ng-repeat 在 AngularJS 的 $interpolate 服务中工作
【发布时间】:2014-01-03 19:24:22
【问题描述】:

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

我在 http://plnkr.co/edit/Cuku7qaUTL1lxRkafKzv 有一个 plunker,它不工作,因为我不知道如何在 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>

【问题讨论】:

    标签: javascript angularjs twitter-bootstrap


    【解决方案1】:

    $interpolate 不处理像 ngRepeat 这样的指令( Difference between parse, interpolate and compile)。 $interpolate

    将带有标记的字符串编译为插值函数。这 服务被 HTML $compile 服务用于数据绑定。

    处理ngRepeat 和您想要$compile 的其他指令。但不幸的是,对于您的用例$compile 将导致一些变化,因为:

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

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

    • 需要在弹出窗口位于 dom 时进行编译。

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

    所以我们不能在您的服务中将$interpolate 替换为$compile

    一种方法是将data-ng-bind-html 替换为以下指令,该指令的作用类似于具有内置$compileng-bind-html(显然,您应该只将其与您知道安全的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 在范围内。有几种处理方法 - 但出于演示目的,我手动返回到调用弹出框的范围 - 这是 2 个范围,因此是 scope.$parent.$parent

    使用这个编译指令你不再$interpolate$sanitize所以你的服务中的函数可以缩小到只返回适当的模板:

    function html_for() {
      var template = $templateCache.get('thingyTemplate.html');
      return template;
    }
    

    demo fiddle

    【讨论】:

      猜你喜欢
      • 2023-03-19
      • 2017-12-22
      • 2018-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-03
      • 1970-01-01
      相关资源
      最近更新 更多