【问题标题】:Process Angularjs Directive From Bound Value Which Returns HTML从返回 HTML 的绑定值处理 Angularjs 指令
【发布时间】:2014-04-05 00:30:04
【问题描述】:

我不确定标题是否正确。我正在做的事情有点过头了,因为我对 Angular 还很陌生。

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

这是一个插曲: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>

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

这是&lt;code&gt;的指令

.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 过滤器。我将它传递给过滤器的原因是因为在我的应用程序中还有一点,突出显示方法是在没有&lt;code&gt; 标签的情况下完成的,所以它适用于我正在做的事情(最少的代码重复)。我想我应该使用 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 不处理(正确的词是什么?我知道它没有处理)将值吐到屏幕上(原因很明显)

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

<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);
          });
        }
      }
    }
  ])

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

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

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

我的梦想是像第一个示例一样设置 pre 标签:

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

因为它看起来有点合适,但我在这里乞求不要选择。如果有人能帮助我一点点,我将非常感激。我完全被困住了,我什至不知道该谷歌什么了。

【问题讨论】:

标签: javascript angularjs angularjs-directive


【解决方案1】:

哇,你真的错过了SCE
导入$sce 依赖项,它代表“严格上下文转义”。这意味着您可以告诉 Angular.js 回显 HTML 而不是对其进行清理。
例如,$scope.bacon = $sce.trustAs('html', '&lt;b&gt;bacon!&lt;/b&gt;'),然后&lt;div ng-bind-html="bacon"&gt;&lt;/div&gt; 将产生 bacon!

【讨论】:

    【解决方案2】:

    一段很棒的代码,您只需禁用 SCE 即可处理要处理的字符串。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-24
      • 1970-01-01
      • 1970-01-01
      • 2015-04-19
      • 1970-01-01
      • 1970-01-01
      • 2019-02-10
      • 1970-01-01
      相关资源
      最近更新 更多