Angular ng-bind-html 和其中的指令

Posted

技术标签:

【中文标题】Angular ng-bind-html 和其中的指令【英文标题】:angular ng-bind-html and directive within it 【发布时间】:2013-06-29 08:23:24 【问题描述】:

Plunker Link

我有一个想要绑定 html 的元素。

<div ng-bind-html="details" upper></div>

这行得通。现在,连同它,我还有一个绑定到绑定 html 的指令:

$scope.details = 'Success! <a href="#/details/12" upper>details</a>'

但是带有 div 和锚点的指令 upper 不计算。如何让它发挥作用?

【问题讨论】:

看我的答案***.com/questions/17343696/… @Chandermani 没有完全使用 ng-bind-html-unsafe 中的指令,而是使用了过滤器。但它会做,我只是创建了一个过滤器并传递给指令。谢谢! @SamSerious 你能说明你是如何为过滤器做的吗? 以上解决方案不处理值的多次变化更好的解决方案***.com/a/25516311/3343425 【参考方案1】:

添加这条指令angular-bind-html-compile

.directive('bindHtmlCompile', ['$compile', function ($compile) 
  return 
    restrict: 'A',
    link: function (scope, element, attrs) 
      scope.$watch(function () 
        return scope.$eval(attrs.bindHtmlCompile);
      , function (value) 
        // Incase value is a TrustedValueHolderType, sometimes it
        // needs to be explicitly called into a string in order to
        // get the HTML string.
        element.html(value && value.toString());
        // If scope is provided use it, otherwise use parent scope
        var compileScope = scope;
        if (attrs.bindHtmlScope) 
          compileScope = scope.$eval(attrs.bindHtmlScope);
        
        $compile(element.contents())(compileScope);
      );
    
  ;
]);

像这样使用它:

<div bind-html-compile="data.content"></div>

真的很简单:)

【讨论】:

小心,如果你传递这样的东西: "$scope.loadContent = function() return $sce.trustAsHtml(require('html/main-content.html')); ; "对它你可以获得无限的摘要循环。没有 trustAsHtml 它可以工作。【参考方案2】:

对于任何处理已经通过$sce.trustAsHtml 运行的内容的人来说,这是我必须做的不同

function(scope, element, attrs) 
    var ensureCompileRunsOnce = scope.$watch(function(scope) 
            return $sce.parseAsHtml(attrs.compile)(scope);
        ,
        function(value) 
            // when the parsed expression changes assign it into the current DOM
            element.html(value);

            // compile the new DOM and link it to the current scope.
            $compile(element.contents())(scope);

            // Use un-watch feature to ensure compilation happens only once.
            ensureCompileRunsOnce();
        );

这只是指令的link 部分,因为我使用的是不同的布局。您将需要注入$sce 服务以及$compile

【讨论】:

【参考方案3】:

我也遇到了这个问题,在互联网上搜索了几个小时后,我阅读了@Chandermani 的评论,这被证明是解决方案。 您需要使用此模式调用“编译”指令:

HTML:

<div compile="details"></div>

JS:

.directive('compile', ['$compile', function ($compile) 
    return function(scope, element, attrs) 
        scope.$watch(
            function(scope) 
                // watch the 'compile' expression for changes
                return scope.$eval(attrs.compile);
            ,
            function(value) 
                // when the 'compile' expression changes
                // assign it into the current DOM
                element.html(value);

                // compile the new DOM and link it to the current
                // scope.
                // NOTE: we only compile .childNodes so that
                // we don't get into infinite loop compiling ourselves
                $compile(element.contents())(scope);
            
        );
    ;
])

你可以看到一个工作的fiddle of it here

【讨论】:

在第 2 行,即。 function(scope, element, attrs),你从这三个参数中哪里得到的,scopeelementattrs @spaffy - 它们是 Angular 框架对 link 属性的签名的一部分。每当 Angular 框架调用 link 时,它们都会自动传递。它们将始终可用。 干得好。你为我节省了同样的搜索时间。我正在从 SharePoint 视图 REST API 中提取内容,该 API 本身包含 Angular 标记,例如 ng-repeat。您的指示使一切正常。谢谢! 感谢您的指示,它解决了我遇到的问题。现在角度代码被编译但太多次了。具有 3 个对象的 ng-repeat 变成相同的值,每个值只有 3 倍。这里出了什么问题? 如果您一直在使用来自另一个函数的$sce.trustAsHtml 创建将使用此指令“编译”的 HTML,您应该删除它。感谢@apopxy【参考方案4】:

很遗憾,我没有足够的声誉来发表评论。

我无法让它工作很长时间。我修改了我的 ng-bind-html 代码以使用此自定义指令,但我未能删除 ng-bind-html 工作所需的 $scope.html = $sce.trustAsHtml($scope.html)。一旦我删除它,编译功能就开始工作了。

【讨论】:

【参考方案5】:

我发现的最佳解决方案!我复制了它,它完全符合我的需要。谢谢,谢谢,谢谢...

在指令链接函数中我有

app.directive('element',function($compile)
  .
  .
     var addXml = function()
     var el = $compile('<xml-definitions definitions="definitions" />')($scope);
     $scope.renderingElement = el.html();
     
  .
  .

在指令模板中:

<span compile="renderingElement"></span>

【讨论】:

【参考方案6】:

感谢 vkammerer 的出色回答。我建议的一项优化是在编译运行一次后不观看。 watch 表达式中的 $eval 可能会对性能产生影响。

    angular.module('vkApp')
  .directive('compile', ['$compile', function ($compile) 
      return function(scope, element, attrs) 
          var ensureCompileRunsOnce = scope.$watch(
            function(scope) 
               // watch the 'compile' expression for changes
              return scope.$eval(attrs.compile);
            ,
            function(value) 
              // when the 'compile' expression changes
              // assign it into the current DOM
              element.html(value);

              // compile the new DOM and link it to the current
              // scope.
              // NOTE: we only compile .childNodes so that
              // we don't get into infinite loop compiling ourselves
              $compile(element.contents())(scope);

              // Use un-watch feature to ensure compilation happens only once.
              ensureCompileRunsOnce();
            
        );
    ;
]);

Here's a forked and updated fiddle.

【讨论】:

我可以反过来吗? 这不是响应 ajax 的工作,而是接受的答案工作 警告:此答案的小提琴有效,但答案中发布的代码中的.directive() 代码无效。 这个对我有用。选择的答案将触发“错误:$rootScope:infdig Infinite $digest Loop” 您不需要显式的$eval - 您可以直接使用attrs.compile 代替被监视的匿名函数。如果你只提供一个字符串表达式,Angular 无论如何都会调用$eval

以上是关于Angular ng-bind-html 和其中的指令的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 ng-bind-html 插入 Angular 1.5 组件

使用 ng-bind-html 来自 Angular Array 的 iframe 视频

angularjs ng-bind-html的用法总结

angularjs 可以加入html标签方法------ng-bind-html的用法总结

angularjs 可以加入html标签方法------ng-bind-html的用法总结

Angular指令总结