【问题标题】:Insert HTML into view from AngularJS controller从 AngularJS 控制器将 HTML 插入视图
【发布时间】:2012-03-12 00:30:30
【问题描述】:

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

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

我创建了一个模型属性,但如果不打印 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>

【问题讨论】:

  • 另请参阅this question,询问是否可以让插入的 HTML 中的脚本运行。
  • 是否可以将多个对象绑定到同一个 ng-bind?像```ng-bind="site.address_1 site.address_2 site.zip"
  • 如果您的页面上有很多东西,您将不得不更改 function htmlSanitizer(html) {... 的 angular.js (insanity) 的第 15046 行。 Angular 开发人员决定,您应该能够通过缓慢地逐个浏览所有页面隐藏元素来找到任何 html 绑定,以找到一个缺失的 html 片段。 !!!对这样的假设非常生气!!!
  • 抱歉,Luke 选择的答案可能不是完全正确的答案。正确答案可以在另一个问题here 中找到。基本上,“ng-bind-html-unsafe 仅将内容呈现为 HTML。它不会将 Angular 范围绑定到生成的 DOM。您必须为此目的使用 $compile 服务。”
  • ng-bind 删除所有内部 html。这不是过滤器的工作方式,当过滤器是唯一的值时没关系

标签: javascript angularjs escaping html-sanitizing


【解决方案1】:

对于 Angular 1.x,在 HTML 中使用 ng-bind-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);

ngSanitize

有两个步骤:

  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'])
    

【讨论】:

  • 在 Angular 1.2 中,ng-bind-html-unsafe 被删除,两个指令被合并。见:github.com/angular/angular.js/blob/master/…
  • 不使用 ngSanitize,现在可以使用 $sce 来完成。将其注入控制器并通过它传递 html。 $scope.thisCanBeusedInsideNgBindHtml = $sce.trustAsHtml(someHtmlVar); 否则我一直收到attempting to use an unsafe value in a safe context
  • 我们需要在这里进行一些清理,这是正确的方法,似乎没有什么对我有用。
  • 为了让人们不会灰心,这个答案的最新更新,加上答案底部的 ngSanitize 要求,确实有效。
【解决方案2】:

你也可以像这样创建一个过滤器:

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 依赖不是必需的。
  • 仅当您完全信任 HTML 时才使用此选项。这不会以任何方式清理 HTML,而仅允许 Angular 将其注入页面。恶意 HTML 会引发 XSS 攻击。
  • 如果性能很重要,您应该避免使用过滤器。一个过滤器每次都会触发两个摘要。
  • 过滤器为什么叫sanitize?这非常具有误导性,因为它实际上并没有对任何东西进行消毒。相反,它应该被称为trusttrustSafe 或类似的名称。
  • 精彩的答案。 rawHtml 是我的过滤器名称,而不是 sanitize
【解决方案3】:

Angular JS shows HTML within the tag

上面链接中提供的解决方案对我有用,这个线程上的选项都没有。对于任何寻找与 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>

【讨论】:

  • 请注意,您需要绝对确定 html 是可以信任的。否则 XSS 攻击的大门是敞开的。
  • 这个解决方案,使用一个函数来呈现 HTML,是唯一对我有用的解决方案。
  • '$http' 是干什么用的?
  • @SoldeplataSaketos 没什么特别的,我想我当时是在本地尝试,最后我复制了依赖项。
  • 此处更新相同的答案。 stackoverflow.com/questions/21829275/…
【解决方案4】:

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

sanitize 模块必须包含在 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答案

【讨论】:

  • 尝试一些像&lt;div&gt;&lt;label&gt;Why My Input Element Missing&lt;/label&gt;&lt;input /&gt;&lt;/div&gt;这样的html...如果它让你感到惊讶,那么请更新你的答案。因为我测试了所有10+投票解决方案..你的解决方案对我来说不起作用输入标签.. 否则很好.. 我用过$sce.trustAsHtml(html)
  • 此解决方案有效,请发布 jsfiddle 或 plunkr?
  • 如果使用最新的角度,这应该是真正的答案
【解决方案5】:

我今天试过了,我发现的唯一方法就是这个

&lt;div ng-bind-html-unsafe="expression"&gt;&lt;/div&gt;

【讨论】:

  • 只有在来源可信的情况下才应使用此解决方案以避免跨站点脚本攻击。
  • 从 Angular 1.0.2 开始,这对我有用,不需要其他文件或连接。
  • 使用 Angular 1.0.8 这对我有用。不过请注意@Bertrand 的警告,请确保您信任消息来源。
  • 在 1.2 版中删除了 ng-bind-html-unsafe 以供将来参考。现在您需要 ngSanitize 模块并绑定不安全的 html,您应该使用 $sce.trustAsHtml 方法。
【解决方案6】:

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

这是最短的方法:

创建过滤器:

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

在你看来:

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

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

【讨论】:

  • 这是我在这里看到的 Angular 1.2 的最佳解决方案。在接受的答案中使用$sce 的解决方案对我不起作用,我不想为如此琐碎的事情添加额外的依赖项。
  • Bidhan Bhattarai 的解决方案对我有用。角 1.6.1
【解决方案7】:

在 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);

【讨论】:

  • $sce 很简洁,但用户不能在这里添加断点并使用调试器将任何恶意代码恢复到this.myCtrl.comment.msg 吗?
  • 然后是 BradGreens,您是否也可以对 ng-bind-html-unsafe 做同样的事情?
  • 如果有人想破解他们自己的浏览器,谁在乎。它不会影响其他用户。 @BradGreens 是这个问题吗?
  • @ChrisStephens 你是对的。我想这确实回答了我的问题,但我认为这些功能更接近于感知安全而不是真正的安全。也许它可以防止某种自动攻击?我从来没有清楚地理解为什么做这些事情真的对应用程序有帮助。我的应用程序必须为渲染所见即所得 HTML 的每个实例添加一个过滤器,因为它可能具有内联 CSS,而 ng-bind-html 将其剥离。
  • 这些功能有助于减少安全编码错误。特别是标记/代码注入的问题。默认情况下,所有绑定数据都经过编码以供显示。所以基本上,如果你想输出标记,这会迫使你思考你想要做什么。如果没有这些功能,您可以单独使用服务器端安全性来做很多事情,但为了区分客户端应用程序应该负责正确处理数据以进行显示的问题。
【解决方案8】:

我发现使用 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>

祝你好运。

【讨论】:

    【解决方案9】:

    刚刚通过关注angular(v1.4) docs 使用 ngBindHtml 完成此操作,

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

    确保在模块的依赖项中包含 ngSanitize。 那么它应该可以正常工作。

    【讨论】:

      【解决方案10】:

      另一个与 blrbr 非常相似的解决方案是:

      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()

      【讨论】:

        【解决方案11】:

        对于这个问题,还有另一种解决方案,即在 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

        【讨论】:

          【解决方案12】:

          您也可以使用 ng-include

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

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

          【讨论】:

          • 您确定这就是使用 ng-include 所需要做的全部事情吗?
          • 是的..我已经试过了。如果您正在使用模板,请按以下方式使用它 -
          【解决方案13】:

          这里是解决方案制作这样的过滤器

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

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

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

          感谢鲁本·德克罗普

          【讨论】:

            【解决方案14】:

            使用

            <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>
            

            【讨论】:

              【解决方案15】:

              这是一个简单(且不安全)的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>
              

              【讨论】:

                【解决方案16】:

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

                1.Crated Pipe escape-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. 在您的模板中使用

                      &lt;div class="demoPipe"  [innerHtml]="getDivHtml(obj.header) | keepHtml"&gt;
                2. getDivHtml() { //can return html as per requirement}

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

                【讨论】:

                • 我认为他正在使用 AngularJS,而不是较新的版本。
                【解决方案17】:

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

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

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

                【讨论】:

                • 这仅适用于 Angular(Angular 版本 2+),不适用于 AngularJS(Angular 版本 1)。
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多