从返回HTML的绑定值处理Angularjs指令

时间:2014-04-05 00:30:04

标签: javascript angularjs angularjs-directive

我不确定标题是否正确。我正在做的事情有点过头了,因为我对Angular相当新。

我试图让一个来自绑定值的指令运行。该指令返回HTML。我的问题是试图让HTML显示。我想我错过了转换的概念(因为我没有使用它),我搞砸了。

这是一个小伙伴:http://plnkr.co/edit/fRhpsS97IGbTWtDPCMlI?p=preview

我的范围内的数据如下所示:

$scope.data = [{
        details: 'IUt euismod tellus, at posuere sem. <code lang="java">int foo = 21;</code> Nullam mattis ac elit in gravida.'
      }, 
      {
        details: 'BHA BHA BHA e sem. <code lang="java">int wutWut = 56;</code> Nullam mattis ac elit in gravida. Sed nec ipsum sed urna.'
      }
    ];

我显示如下数据:

<pre ng-repeat="item in data">
  {{item.details}}
</pre>

一切正常,但问题是我需要将<code>标签(来自item.details)作为指令处理。所述指令应该读取lang属性,并使用包含的Sunlight Syntax Highlighter正确突出显示该元素的内容。

所以这里是<code>

的指令
.directive('code', ['$filter',
    function($filter) {
      return {
        restrict: 'E',
        replace: true,
        scope: {
          lang: '@'
        },
        controller: ['$scope','$element',
          function($scope, $element) {
            // default lang
            if (typeof $scope.lang === 'undefined')
              $scope.lang = 'java';

            $scope.src = $element.html();
          }
        ],
        template: '<span>{{src | codeHighlight:lang}}</span>'
      };
    }
  ]);

基本上只是将这些位传递给codeHighlight过滤器。我将其传递给过滤器的原因是因为我的应用程序中的另一个点是突出显示方法没有<code>标记,所以它适用于我正在做的事情(最小代码重复) )。我认为我应该使用transclude选项和$ filter服务,但我不能100%确定如何获取标记之间的值。

这是我的codeHighlight过滤器。这使用Sunlight lib进行突出显示。所以它将HTML作为字符串返回。当我直接使用它时,我通常会这样做:ng-bind-html="foo.bar | codeHighlight | safeHtml"

.filter('codeHighlight', function() {

    return function(code, lang) {
      // Default lang
      if (typeof lang === 'undefined')
        lang = 'java';

      // Grab a highlighter
      var highlighter = new Sunlight.Highlighter();
      var context = highlighter.highlight(code, lang);
      var el = angular.element(context.getNodes());
      var html = el.wrap('<p/>').parent().html();

      // Convert nbsp's to actual spaces (so line breaks work better)
      html = html.replace(/&nbsp;/gi, ' ');

      return html;
    };

  })

这里的safeHtml过滤器只是为了理智,但并不适用于我的问题

.filter('safeHtml', ['$sce',function($sce){
    return function(html){
      return $sce.trustAsHtml(html);
    };
  }])

所有这一切都有效,除了原始的data.details永远不会被处理,因为Angular没有处理(什么是正确的词?我知道它不是处理)值吐出来屏幕(显而易见的原因)

所以我修改输出并创建一个指令来重新编译输出值。我使用编译属性,因为我不明白如何正确拉动链接?标签之间的数据。

<pre ng-repeat="item in data" compile="item.details"></pre>

这里是compile指令

.directive('compile', ['$compile',
    function($compile) {
      return {
        restrict: 'A',
        link: function(scope, element, attrs) {
          scope.$watch(attrs.compile, function(html) {
            element.html(html);
            $compile(element.contents())(scope);
          });
        }
      }
    }
  ])

所以现在一切正常! NEATO!除了我的html显示为字符串,因为Angular清理输出。不幸的是,我知道如何将原始HTML打印到页面的唯一方法是使用ng-bind-html指令,我不能这样做因为我使用了我的愚蠢compile指令。

我想也许在watch函数中我可以在element.html(element.html())函数之后追加$compile,但这只是返回原始模板。

显然,我进入了一个我不完全理解的领域。

我的梦想是在第一个例子中设置预标签:

<pre ng-repeat="item in data" compile="item.details">
  {{item.details}}
</pre>

因为它看起来很合适,但我在这里乞求不选择。如果有人能帮我一点,我会非常感激。我完全陷入困境,我甚至不知道谷歌会怎么做。

2 个答案:

答案 0 :(得分:0)

哇,你真的错过了SCE 导入$sce依赖项,代表“Strict Contextual Escaping”。这意味着您可以告诉Angular.js回显HTML而不是清理它 例如,$scope.bacon = $sce.trustAs('html', '<b>bacon!</b>'),然后<div ng-bind-html="bacon"></div>将导致培根!

答案 1 :(得分:-1)

令人敬畏的一段代码,您只需要为要处理的字符串禁用SCE即可。

angular.module('moduleName').config(function($sceProvider) {
    $sceProvider.enabled(false);
})