角度ng-bind-html和其中的指令


96

柱塞链接

我有一个我想将html绑定到它的元素。

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

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

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

但是upper带有div和anchor 的指令不求值。我该如何运作?



@Chandermani不完全在ng-bind-html-unsafe中使用指令,而是使用过滤器。但这确实可以,我只是创建了一个过滤器并传递给指令。谢谢!
阿米塔瓦2013年

@SamSerious您能够显示出您对过滤器的处理方式吗?
CMCDragonkai 2013年

上述解决方案不能处理值的多次更改,更好的解决方案stackoverflow.com/a/25516311/3343425
fghibellini 2014年

Answers:


188

我也遇到了这个问题,经过几个小时的互联网搜索,我读到了@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);
            }
        );
    };
}])

您可以在这里看到它的工作提琴


1
在第2行,即 function(scope, element, attrs),您从那三个参数(作用域元素属性)中得到了什么?
spaffy 2015年

1
@spaffy-它们是该link属性的Angular框架签名的一部分。每次link在Angular框架调用时,它们都会自动传递。它们将始终可用。
2015年

1
做得好。您节省了我同样的搜索时间。我从SharePoint视图REST API中提取内容,该API本身包含Angular标记(例如ng-repeat)。您的指令使一切正常。谢谢!
Phil Nicholas

感谢您的指示,它解决了我遇到的问题。现在,角度代码被编译了很多次。具有3个对象的ng-repeat变成相同的值,每个值只有3x。怎么了
杰森

2
如果您一直在使用$sce.trustAsHtml另一个函数来创建将使用此伪指令“编译”的HTML,则应将其删除。感谢@apoplexy
Burak Tokak '17

36

感谢您的出色答案vkammerer。我建议的一种优化是编译运行一次后取消监视。监视表达式中的$ 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();
            }
        );
    };
}]);

这是一个分叉的和更新的小提琴。


反之亦然吗?
Sanyam Jain 2015年

这不是针对Ajax的工作,而是可接受的答案工作
foozhan 2015年

1
警告:此答案的小提琴有效,但.directive()答案中张贴的代码中的代码无效。
Phil Nicholas

这个为我工作。选择的答案将触发“错误:$ rootScope:infdig无限$ digest循环”
Gabriel Andrei

您不需要显式$eval-您可以直接使用attrs.compile它代替受监视的匿名函数。如果您仅提供一个字符串表达式,则angular仍会调用$eval它。
丹·金

28

添加此指令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>

真的很简单:)


1
请小心,如果您传递这样的信息:“ $ scope.loadContent = function(){return $ sce.trustAsHtml(require('html / main-content.html'));};” 为此,您可以获得无限的摘要循环。没有trustAsHtml,它就可以工作。
Lakatos Gyula 2015年

13

不幸的是,我没有足够的声誉来发表评论。

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


6

对于任何已经处理过$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


-2

我发现的最佳解决方案!我复制了它,并且它完全按照我的需要工作。谢谢,谢谢,谢谢...

在指令链接功能中我有

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

在指令模板中:

<span compile="renderingElement"></span>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.