从AngularJS控制器将HTML插入视图


800

是否可以在AngularJS控制器中创建HTML片段并将该HTML显示在视图中?

这是因为需要将不一致的JSON Blob转换为嵌套的id: value对对列表。因此,在控制器中创建了HTML,现在我希望显示它。

我创建了一个model属性,但是如果不打印HTML便无法在视图中呈现它。


更新资料

看起来问题出在将创建的HTML角化为引号内的字符串而引起。将尝试找到解决此问题的方法。

控制器示例:

var SomeController = function () {

    this.customHtml = '<ul><li>render me please</li></ul>';
}

示例视图:

<div ng:bind="customHtml"></div>

给:

<div>
    "<ul><li>render me please</li></ul>"
</div>

1
另外,请参阅此问题,询问是否可以在插入的HTML中运行脚本。
enigment

是否可以将多个对象绑定到同一个ng-bind?就像```ng-bind =“ site.address_1 site.address_2 site.zip”
fauverism

如果您的页面上有很多东西,则必须更改的angular.js(精神错乱)行15046 function htmlSanitizer(html) {...。Angular开发人员决定,通过逐步浏览所有页面中的隐藏元素以找到缺少html的单个元素,您应该能够找到任何html绑定。!!! 对这样的假设非常生气!
user3338098 2015年

抱歉,卢克选择的答案可能不是完全正确的答案。正确的答案可以在这里的另一个问题中找到。基本上,“ ng-bind-html-unsafe仅将内容呈现为HTML。它不会将Angular范围绑定到生成的DOM。为此,您必须使用$ compile服务。”
gm2008

ng-bind删除所有内部html。这不是过滤器如何工作的,当过滤器是唯一的值时没关系
Muhammad Umer 16'July

Answers:


1120

对于Angular 1.x,ng-bind-html在HTML中使用:

<div ng-bind-html="thisCanBeusedInsideNgBindHtml"></div>

此时,您将得到一个attempting to use an unsafe value in a safe context错误,因此您需要使用ngSanitize$ sce来解决该问题。

$ sce

$sce.trustAsHtml()在控制器中使用以转换html字符串。

 $scope.thisCanBeusedInsideNgBindHtml = $sce.trustAsHtml(someHtmlVar);

ng消毒

分两个步骤:

  1. 包括angular-sanitize.min.js资源,即:
    <script src="lib/angular/angular-sanitize.min.js"></script>

  2. 在js文件(控制器或通常为app.js)中,包括ngSanitize,即:
    angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives', 'ngSanitize'])


30
在Angular 1.2中,将ng-bind-html-unsafe其删除并合并了两个指令。请参阅:github.com/angular/angular.js/blob/master/...
萨沙Chedygov

60
无需使用ngSanitize,现在可以使用来完成$sce。将其注入控制器,然后将html传递给它。$scope.thisCanBeusedInsideNgBindHtml = $sce.trustAsHtml(someHtmlVar);否则我会不断得到attempting to use an unsafe value in a safe context
Matsemann

3
我们需要在这里进行一些清理,这是正确的方法,似乎对我来说都不起作用。
2014年


7
只是这样,人们不会灰心,答案的最新更新以及答案底部的ngSanitize要求实际上是有效的。
Ben Cull 2014年

312

您还可以像这样创建过滤器:

var app = angular.module("demoApp", ['ngResource']);

app.filter("trust", ['$sce', function($sce) {
  return function(htmlCode){
    return $sce.trustAsHtml(htmlCode);
  }
}]);

然后在视图中

<div ng-bind-html="trusted_html_variable | trust"></div>

注意:此过滤器信任传递给它的所有HTML,并且如果将带有用户输入的变量传递给它,则可能呈现XSS漏洞。


@Katie Astrauskas,谢谢你的回答!很干净的方法。BTW ngResource依赖不是必需的。
Athlan

28
仅在完全信任HTML时才使用它。这不会以任何方式清除HTML,而仅允许Angular将其注入到页面中。恶意HTML可以引发XSS攻击。
jan.vdbergh 2015年

如果性能很重要,则应避免使用过滤器。过滤器每次都会触发两个摘要。
2015年

14
为什么叫过滤器sanitize?这是如此令人误解,因为它实际上没有对任何东西进行消毒。相反,它应该叫trusttrustSafe或者类似的东西。
Denis Pshenov 2015年

1
很棒的答案。rawHtml是我的过滤器名称,而不是sanitize
Wumms,2015年

119

Angular JS在标记中显示HTML

上面链接中提供的解决方案对我有用,该线程上的所有选项均无效。对于使用AngularJS 1.2.9版寻找相同内容的任何人

这是副本:

好的,我找到了解决方案:

JS:

$scope.renderHtml = function(html_code)
{
    return $sce.trustAsHtml(html_code);
};

HTML:

<p ng-bind-html="renderHtml(value.button)"></p>

编辑:

设置如下:

JS档案:

angular.module('MyModule').controller('MyController', ['$scope', '$http', '$sce',
    function ($scope, $http, $sce) {
        $scope.renderHtml = function (htmlCode) {
            return $sce.trustAsHtml(htmlCode);
        };

        $scope.body = '<div style="width:200px; height:200px; border:1px solid blue;"></div>'; 

    }]);

HTML档案:

<div ng-controller="MyController">
    <div ng-bind-html="renderHtml(body)"></div>
</div>

7
请注意,您需要绝对确保可以信任html。否则,对于XSS攻击的大门是敞开的。
jan.vdbergh 2015年

此解决方案使用一种功能来呈现HTML,是唯一对我有用的解决方案。
MarceloBarbosa

“ $ http”的作用是什么?
Soldeplata Saketos

@SoldeplataSaketos没什么特别的,我想我当时正在本地尝试,最终我将依赖项复制了过来。
anpatel


65

幸运的是,您不需要任何奇特的过滤器或不安全的方法来避免出现该错误消息。这是完整的实现,可以以预期的安全方式在视图中正确输出HTML标记。

清理模块必须包含在Angular之后:

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular-sanitize.js"></script>

然后,必须加载模块:

angular.module('app', [
  'ngSanitize'
]);

这将允许您在控制器,指令等的字符串中包含标记:

scope.message = "<strong>42</strong> is the <em>answer</em>.";

最后,在模板中,必须这样输出:

<p ng-bind-html="message"></p>

这将产生预期的输出:42答案


1
尝试一些类似html的代码<div><label>Why My Input Element Missing</label><input /></div>……如果您感到惊讶,请更新您的答案。。因为我测试了所有10种以上的投票解决方案。$sce.trustAsHtml(html)
2015年

此解决方案有效,是否愿意发布jsfiddle或plunkr?
2015年

如果使用最新的角度,这确实应该是答案
Sandeep,2015年

61

我今天尝试过,我发现的唯一方法是

<div ng-bind-html-unsafe="expression"></div>


6
仅当源是可信任的以避免跨站点脚本攻击时,才应使用此解决方案。
2012年

3
从Angular 1.0.2开始,这对我有效,不需要其他文件或连接。
enigment 2012年

1
使用Angular 1.0.8,这对我有用。但是请注意@Bertrand的警告,请确保您信任源。
杰克·斯林格兰

12
为了将来参考,在1.2版中删除了ng-bind-html-unsafe。现在,您需要ngSanitize模块,并绑定不安全的html,您应该使用$ sce.trustAsHtml方法。
卢卡斯·拉萨罗

53

ng-bind-html-unsafe 不再有效。

这是最短的方法:

创建一个过滤器:

myApp.filter('unsafe', function($sce) { return $sce.trustAsHtml; });

在您看来:

<div ng-bind-html="customHtml | unsafe"></div>

PS此方法不需要您包含ngSanitize模块。


3
这是我在这里针对Angular 1.2看到的最好的解决方案。$sce在接受的答案中使用的解决方案对我而言不起作用,我不想为如此琐碎的事情添加额外的依赖关系。
丹尼尔·邦内尔

Bidhan Bhattarai的解决方案为我工作。Angular 1.6.1
mediaguru

25

在HTML上

<div ng-controller="myAppController as myCtrl">

<div ng-bind-html-unsafe="myCtrl.comment.msg"></div>

要么

<div ng-bind-html="myCtrl.comment.msg"></div

在控制器上

mySceApp.controller("myAppController", function myAppController( $sce) {

this.myCtrl.comment.msg = $sce.trustAsHtml(html);

也可以与 $scope.comment.msg = $sce.trustAsHtml(html);


1
$sce整洁,但用户不能只是在此处添加断点并this.myCtrl.comment.msg使用调试器还原任何恶意代码吗?
BradGreens 2014年

然后再次是BradGreens,您也可以对ng-bind-html-unsafe进行同样的处理吗?
CodeOverRide 2014年

4
如果有人想在这里拥有自己的浏览器,他们会在乎,谁在乎。它不会影响其他用户。@BradGreens这是问题吗?
克里斯·斯蒂芬斯

@ChrisStephens你是正确的。我想这确实回答了我的问题,但我认为这些功能比真正的安全性更接近可感知的安全性。也许它可以防御某种自动攻击?我从来没有清楚地理解为什么这样做确实对应用程序有帮助。我的应用程序必须为呈现所见即所得HTML的每个实例添加一个过滤器,因为它可能具有内联CSS,从而将其ng-bind-html删除。
布莱德格林(BradGreens),2014年

1
这些功能有助于减少安全的编码错误。特别是标记/代码注入的问题。默认情况下,所有绑定数据都经过编码以供显示。因此,基本上,如果您要输出标记,这将迫使您考虑要执行的操作。没有这些功能,您就可以单独使用服务器端安全性做很多事情,但是要分开解决,客户端应用程序应该负责正确处理数据以进行显示。
克里斯·斯蒂芬斯

9

我发现使用ng-sanitize不允许我在html中添加ng-click。

为了解决这个问题,我添加了一条指令。像这样:

app.directive('htmldiv', function($compile, $parse) {
return {
  restrict: 'E',
  link: function(scope, element, attr) {
    scope.$watch(attr.content, function() {
      element.html($parse(attr.content)(scope));
      $compile(element.contents())(scope);
    }, true);
  }
}
});

这是HTML:

<htmldiv content="theContent"></htmldiv>

祝好运。


6

只是通过遵循angular(v1.4)docs使用ngBindHtml做到了这一点,

<div ng-bind-html="expression"></div> 
and expression can be "<ul><li>render me please</li></ul>"

确保在模块的依赖项中包括ngSanitize。然后它应该工作正常。


4

与blrbr的解决方案非常相似的另一种解决方案是,除了使用scoped属性外,它是:

angular.module('app')
.directive('renderHtml', ['$compile', function ($compile) {
    return {
      restrict: 'E',
      scope: {
        html: '='
      },
      link: function postLink(scope, element, attrs) {

          function appendHtml() {
              if(scope.html) {
                  var newElement = angular.element(scope.html);
                  $compile(newElement)(scope);
                  element.append(newElement);
              }
          }

          scope.$watch(function() { return scope.html }, appendHtml);
      }
    };
  }]);

然后

<render-html html="htmlAsString"></render-html>

请注意,您可以将其替换element.append()element.replaceWith()


3

使用angular 创建新的属性或指令可以解决该问题。

product-specs.html

 <h4>Specs</h4>
        <ul class="list-unstyled">
          <li>
            <strong>Shine</strong>
            : {{product.shine}}</li>
          <li>
            <strong>Faces</strong>
            : {{product.faces}}</li>
          <li>
            <strong>Rarity</strong>
            : {{product.rarity}}</li>
          <li>
            <strong>Color</strong>
            : {{product.color}}</li>
        </ul>

app.js

 (function() {
var app = angular.module('gemStore', []);    
app.directive("     <div ng-show="tab.isSet(2)" product-specs>", function() {
return {
  restrict: 'E',
  templateUrl: "product-specs.html"
};
});

index.html

 <div>
 <product-specs>  </product-specs>//it will load product-specs.html file here.
 </div>

要么

<div  product-specs>//it will add product-specs.html file 

要么

<div ng-include="product-description.html"></div>

https://docs.angularjs.org/guide/directive


3

您还可以使用ng-include

<div class="col-sm-9 TabContent_container" ng-include="template/custom.html">
</div>

您可以使用“ ng-show”显示隐藏此模板数据。


您确定这是使用ng-include所需要做的吗?
fauverism

是的..我已经尝试过了。如果您使用的是模板,则按以下方式使用它-<script type =“ text / ng-template” id =“ custom.html”>
Vikash Sharma

2

这是解决方案使像这样的过滤器

.filter('trusted',
   function($sce) {
     return function(ss) {
       return $sce.trustAsHtml(ss)
     };
   }
)

并将其作为过滤器应用于ng-bind-html之类

<div ng-bind-html="code | trusted">

并感谢鲁本·德罗普


1

采用

<div ng-bind-html="customHtml"></div>

angular.module('MyApp', ['ngSanitize']);

为此,例如,您需要angular-sanitize.js在html文件中添加,

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular-sanitize.js"></script>

0

这是一个简单(bind-as-html且不安全)的指令,不需要ngSanitize

myModule.directive('bindAsHtml', function () {
    return {
        link: function (scope, element, attributes) {
            element.html(scope.$eval(attributes.bindAsHtml));
        }
    };
});

请注意,如果绑定不受信任的内容,这将打开安全性问题。

像这样使用:

<div bind-as-html="someHtmlInScope"></div>

-1

使用管道的示例,使用Angular 4在模板中显示html。

1.Cated管道逸出html.pipe.ts

`

import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
@Pipe({name : 'keepHtml', pure : false})
export class EscapeHtmlPipe implements PipeTransform{
 constructor(private sanitizer : DomSanitizer){
 }
 transform(content){
  return this.sanitizer.bypassSecurityTrustHtml(content);
 }
}

`2.将管道注册到app.module.ts

 import {EscapeHtmlPipe} from './components/pipes/escape-html.pipe';
    declarations: [...,EscapeHtmlPipe]
  1. 在模板中使用

        <div class="demoPipe"  [innerHtml]="getDivHtml(obj.header) | keepHtml">

  2. getDivHtml() { //can return html as per requirement}

    请在关联的component.ts文件中为getDivHtml添加适当的实现。


1
我认为他正在使用AngularJS,而不是较新的版本。
麻风病

-1

只需简单使用[innerHTML],如下所示:

<div [innerHTML]="htmlString"></div>

在您需要使用之前ng-bind-html...


仅在Angular(Angular版本2+)中可用,而在AngularJS(Angular版本1)中不可用。
ste2425

-1

在Angular 7 + ionic 4中,可以使用“ [innerHTML]”显示HTML内容:

<div [innerHTML]="htmlContent"></div>

希望对您有帮助。谢谢。


请告诉我这段代码有什么问题,这是导致对此文章投反对票的原因。我已经在我的2个应用程序中测试了此代码。有用。请分享您的经验。非常感谢。
Kamlesh

1
AngularJS等于Angular1.x。角7是一个完全不同的框架
胡管理单元
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.