Chèn HTML vào chế độ xem từ bộ điều khiển AngularJS


800

Có thể tạo một đoạn HTML trong bộ điều khiển AngularJS và hiển thị HTML này trong dạng xem không?

Điều này xuất phát từ yêu cầu biến một blob JSON không nhất quán thành một danh sách các id: valuecặp được lồng vào nhau . Do đó, HTML được tạo trong bộ điều khiển và bây giờ tôi đang tìm cách hiển thị nó.

Tôi đã tạo một thuộc tính mô hình, nhưng không thể hiển thị điều này trong chế độ xem mà không chỉ in HTML .


Cập nhật

Có vẻ như vấn đề phát sinh từ việc hiển thị góc đã tạo HTML dưới dạng một chuỗi trong dấu ngoặc kép. Sẽ cố gắng tìm cách xung quanh này.

Bộ điều khiển ví dụ:

var SomeController = function () {

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

Xem ví dụ:

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

Cung cấp:

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

1
Ngoài ra, vui lòng xem câu hỏi này , hỏi xem có thể lấy các tập lệnh trong HTML được chèn để chạy không.
ban hành

Có thể có nhiều đối tượng liên kết với cùng một ng-bind không? như `` `ng-bind =" site.address_1 site.address_2 site.zip "
fauverism

nếu bạn có nhiều nội dung trên trang của mình, bạn sẽ phải thay đổi dòng 15046 của angular.js (điên rồ) function htmlSanitizer(html) {.... Angular dev đã quyết định rằng bạn sẽ có thể tìm thấy bất kỳ ràng buộc html nào bằng cách từ từ đi qua tất cả các trang của bạn từng phần tử ẩn để tìm thấy một mảnh html bị thiếu. !!! rất tức giận với một giả định như vậy !!!
dùng3338098

Xin lỗi, câu trả lời được chọn của Luke có thể không phải là câu trả lời hoàn toàn đúng. Câu trả lời đúng có thể được tìm thấy trong một câu hỏi khác ở đây . Về cơ bản, "ng-bind-html-không an toàn chỉ hiển thị nội dung dưới dạng HTML. Nó không liên kết phạm vi góc với DOM kết quả. Bạn phải sử dụng dịch vụ $ compile cho mục đích đó."
gm2008

ng-bind loại bỏ tất cả html nội bộ. đó không phải là cách bộ lọc hoạt động, sẽ ổn khi bộ lọc là giá trị duy nhất
Muhammad Umer

Câu trả lời:


1120

Đối với Angular 1.x, sử dụng ng-bind-htmltrong HTML:

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

Tại thời điểm này, bạn sẽ gặp attempting to use an unsafe value in a safe contextlỗi, do đó bạn cần sử dụng ngSanitize hoặc $ sce để giải quyết vấn đề đó.

$ sce

Sử dụng $sce.trustAsHtml()trong bộ điều khiển để chuyển đổi chuỗi html.

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

ngSanitize

Có 2 bước:

  1. bao gồm tài nguyên angular-sanitize.min.js, nghĩa là:
    <script src="lib/angular/angular-sanitize.min.js"></script>

  2. Trong tệp js (trình điều khiển hoặc thường là app.js), bao gồm ngSanitize, nghĩa là:
    angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives', 'ngSanitize'])


30
Trong Angular 1.2, ng-bind-html-unsafeđã được gỡ bỏ và hai chỉ thị được kết hợp. Xem: github.com/angular/angular.js/blob/master/ từ
Sasha Chedygov

60
Không cần sử dụng ngSanitize, có thể thực hiện ngay bây giờ bằng cách sử dụng $sce. Tiêm nó vào bộ điều khiển và chuyển html qua nó. $scope.thisCanBeusedInsideNgBindHtml = $sce.trustAsHtml(someHtmlVar);Nếu không, tôi tiếp tục nhận đượcattempting to use an unsafe value in a safe context
Matsemann

3
Chúng tôi cần một chút dọn dẹp ở đây, đó là cách đúng đắn dường như không có gì có thể làm việc cho tôi.
hạ cánh

9
stackoverflow.com/questions/21829275/ từ <- làm việc cho tôi :) không có lựa chọn nào trong các câu trả lời ở đây không may làm việc
anpatel

7
Để mọi người không nản lòng, bản cập nhật mới nhất của câu trả lời này, cùng với yêu cầu ngSanitize ở cuối câu trả lời, thực tế có hiệu quả.
Ben Cull

312

Bạn cũng có thể tạo một bộ lọc như vậy:

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

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

Sau đó trong chế độ xem

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

Lưu ý : Bộ lọc này tin tưởng bất kỳ và tất cả html được truyền cho nó và có thể gây ra lỗ hổng XSS nếu các biến có đầu vào của người dùng được truyền cho nó.


@Katie Astrauskas, cảm ơn bạn vì anwer! Cách rất sạch sẽ. ngResourceSự phụ thuộc BTW không phải là cần thiết.
Athlan

28
Chỉ sử dụng điều này khi bạn hoàn toàn tin tưởng vào HTML. Điều này không làm vệ sinh HTML theo bất kỳ cách nào, mà chỉ cho phép Angular đưa nó vào trang. HTML độc hại có thể kích động các cuộc tấn công XSS.
jan.vdbergh

Nếu hiệu suất là quan trọng, bạn nên tránh sử dụng các bộ lọc. Một bộ lọc sẽ kích hoạt hai tiêu hóa mỗi lần.
Tantelope

14
Tại sao bộ lọc được gọi là sanitize? Điều này rất sai lầm vì nó không thực sự vệ sinh bất cứ điều gì. Thay vào đó nó nên được gọi trust, trustSafehoặc một cái gì đó tương tự.
Denis Pshenov

1
Câu trả lời tuyệt vời. rawHtmllà tên của tôi cho bộ lọc thay vì sanitize.
Wumms

119

Angular JS hiển thị HTML trong thẻ

Các giải pháp được cung cấp trong liên kết trên đã làm việc cho tôi, không có tùy chọn nào trong chủ đề này đã làm. Đối với bất cứ ai đang tìm kiếm điều tương tự với AngularJS phiên bản 1.2.9

Đây là một bản sao:

Ok tôi tìm thấy giải pháp cho việc này:

JS:

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

HTML:

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

BIÊN TẬP:

Đây là thiết lập:

Tệp tin:

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

    }]);

Tệp HTML:

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

7
Hãy lưu ý rằng bạn cần phải hoàn toàn chắc chắn rằng html có thể tin cậy được. Nếu không, cánh cửa rộng mở cho các cuộc tấn công XSS.
jan.vdbergh

Giải pháp này, sử dụng một chức năng để hiển thị HTML, là giải pháp duy nhất phù hợp với tôi.
MarceloBarbosa

'$ http' để làm gì?
Soldeplata Saketos

@SoldeplataSaketos không có gì cụ thể, tôi nghĩ rằng tôi đã thử nó tại địa phương và cuối cùng tôi đã sao chép sự phụ thuộc.
anpatel

Cập nhật câu trả lời tương tự ở đây. stackoverflow.com/questions/21829275/ Mạnh
Surya R Praveen

65

May mắn thay, bạn không cần bất kỳ bộ lọc ưa thích hoặc phương pháp không an toàn để tránh thông báo lỗi đó. Đây là triển khai hoàn chỉnh để xuất đánh dấu HTML đúng cách trong chế độ xem theo cách dự định và an toàn.

Mô-đun khử trùng phải được đưa vào sau 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>

Sau đó, mô-đun phải được tải:

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

Điều này sẽ cho phép bạn bao gồm đánh dấu trong một chuỗi từ bộ điều khiển, chỉ thị, v.v .:

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

Cuối cùng, trong một mẫu, nó phải là đầu ra như vậy:

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

Mà sẽ tạo ra sản lượng dự kiến: 42câu trả lời .


1
Hãy thử một số html như <div><label>Why My Input Element Missing</label><input /></div>... Nếu điều đó làm bạn ngạc nhiên thì hãy cập nhật câu trả lời của bạn. Vì tôi đã thử nghiệm tất cả 10 giải pháp bỏ phiếu .. Giải pháp của bạn không hoạt động để tôi thấy các thẻ đầu vào của mình .. tốt thôi .. Tôi đã sử dụng$sce.trustAsHtml(html)
Sami

Giải pháp này hoạt động, quan tâm để đăng một jsfiddle hoặc plunkr?
Cầu tàu-Luc Gendreau

Đây thực sự sẽ là câu trả lời nếu sử dụng góc cạnh mới nhất
Sandeep

61

Tôi đã thử ngày hôm nay, cách duy nhất tôi tìm thấy là

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


6
Giải pháp này chỉ nên được sử dụng nếu nguồn đáng tin cậy để tránh các cuộc tấn công kịch bản chéo trang.
Bertrand

3
Kể từ Angular 1.0.2, điều này hoạt động với tôi, không yêu cầu tập tin hoặc hookup nào khác.
ban hành

1
Sử dụng Angular 1.0.8 và điều này làm việc cho tôi. Tuy nhiên, hãy cảnh báo @ Bertrand, hãy chắc chắn rằng bạn tin tưởng vào nguồn này.
Jack Slingerland

12
Để tham khảo trong tương lai ng-bind-html-không an toàn đã bị xóa trong phiên bản 1.2. Bây giờ bạn cần mô-đun ngSanitize và để liên kết html không an toàn, bạn nên sử dụng phương thức $ sce.trustAsHtml.
Lucas Lazaro

53

ng-bind-html-unsafe công việc ngắn hạn.

Đây là con đường ngắn nhất:

Tạo bộ lọc:

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

Và theo quan điểm của bạn:

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

PS Phương pháp này không yêu cầu bạn bao gồm ngSanitizemô-đun.


3
Đây là giải pháp tốt nhất tôi từng thấy ở đây cho Angular 1.2. Giải pháp sử dụng $scetrong câu trả lời được chấp nhận không hiệu quả với tôi và tôi không muốn bao gồm một phụ thuộc bổ sung cho một cái gì đó quá tầm thường.
Daniel Bonell

Giải pháp của Bidhan Bhattarai làm việc cho tôi. Angular 1.6.1
mediaguru

25

trên html

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

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

HOẶC LÀ

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

trên bộ điều khiển

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

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

cũng làm việc với $scope.comment.msg = $sce.trustAsHtml(html);


1
$scegọn gàng nhưng người dùng không thể chỉ cần thêm một điểm dừng ở đây và khôi phục bất kỳ mã độc hại nào để this.myCtrl.comment.msgsử dụng trình gỡ lỗi?
BradGreen

sau đó một lần nữa BradGreen, bạn có thể làm điều tương tự với ng-bind-html-không an toàn không?
CodeOverRide

4
Nếu ai đó muốn hack có trình duyệt riêng họ có thể, ai quan tâm. Nó sẽ không ảnh hưởng đến người dùng khác. @BradGreen Đó có phải là câu hỏi?
Chris Stephens

@ChrisStephens bạn đúng. Tôi đoán điều đó trả lời câu hỏi của tôi nhưng ý kiến ​​của tôi là những tính năng này gần với bảo mật hơn là bảo mật thực sự. Có lẽ nó bảo vệ chống lại một số loại tấn công tự động? Tôi chưa bao giờ hiểu rõ tại sao làm những việc này thực sự giúp ích cho ứng dụng. Ứng dụng của tôi phải thêm bộ lọc vào MỌI ví dụ hiển thị HTML wysiwyg vì nó có thể có CSS ​​nội tuyến, ng-bind-htmlloại bỏ.
BradGreen

1
Vâng, các tính năng này giúp giảm thiểu sai lầm mã hóa an toàn. Đặc biệt là vấn đề với đánh dấu / tiêm mã. Theo mặc định, tất cả dữ liệu ràng buộc được mã hóa để hiển thị. Vì vậy, về cơ bản nếu bạn muốn đánh dấu đầu ra, điều này buộc bạn phải suy nghĩ về những gì bạn đang cố gắng làm. Nếu không có các tính năng này, bạn có thể làm rất nhiều việc chỉ với bảo mật phía máy chủ nhưng để tách biệt mối lo ngại, ứng dụng khách phải tính phí xử lý dữ liệu một cách chính xác để hiển thị.
Chris Stephens

9

Tôi thấy rằng việc sử dụng ng-sanitize không cho phép tôi thêm ng-click trong html.

Để giải quyết điều này tôi đã thêm một chỉ thị. Như thế này:

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

Và đây là HTML:

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

Chúc may mắn.


6

Chỉ cần làm điều này bằng cách sử dụng ngBindHtml bằng cách làm theo các tài liệu góc (v1.4) ,

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

Đảm bảo bạn bao gồm ngSanitize trong phần phụ thuộc của mô-đun. Sau đó, nó nên hoạt động tốt.


4

Một giải pháp khác, rất giống với blrbr ngoại trừ sử dụng thuộc tính có phạm vi là:

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

Và sau đó

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

Lưu ý bạn có thể thay thế element.append()bằngelement.replaceWith()


3

có thêm một giải pháp cho vấn đề này bằng cách tạo thuộc tính hoặc chỉ thị mới theo góc.

sản phẩm-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>

hoặc là

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

hoặc là

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

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


3

bạn cũng có thể sử dụng ng-gộp .

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

bạn có thể sử dụng "ng-show" để hiển thị ẩn dữ liệu mẫu này.


Bạn có chắc chắn rằng đây là tất cả những gì bạn cần làm để sử dụng ng-gộp?
fauverism

vâng .. tôi đã thử nó và nếu bạn đang sử dụng mẫu thì hãy sử dụng nó theo cách sau - <script type = "text / ng-template" id = "custom.html">
Vikash Sharma

2

Đây là giải pháp tạo bộ lọc như thế này

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

và áp dụng điều này như một bộ lọc cho ng-bind-html như

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

và cảm ơn Ruben Decrop


1

Sử dụng

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

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

Đối với điều đó, bạn cần đưa vào angular-sanitize.js, ví dụ như trong tệp html của bạn với

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

0

Đây là một bind-as-htmlchỉ thị đơn giản (và không an toàn) , không cần ngSanitize:

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

Lưu ý rằng điều này sẽ mở ra cho các vấn đề bảo mật, nếu ràng buộc nội dung không đáng tin cậy.

Sử dụng như vậy:

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

-1

Ví dụ làm việc với ống dẫn để hiển thị html trong mẫu với Angular 4.

1.Crated ống thoát-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. Đăng ký đường ống đến app.module.ts

 import {EscapeHtmlPipe} from './components/pipes/escape-html.pipe';
    declarations: [...,EscapeHtmlPipe]
  1. Sử dụng trong mẫu của bạn

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

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

    Vui lòng thêm triển khai thích hợp cho getDivHtml trong tệp thành phần được liên kết.


1
Tôi nghĩ anh ấy đang làm việc với AngularJS, không phải phiên bản mới hơn.
Bệnh phong

-1

Chỉ cần sử dụng đơn giản [innerHTML], như dưới đây:

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

Trước khi bạn cần sử dụng ng-bind-html...


Điều này chỉ có sẵn trong Angular (phiên bản Angular 2+), không phải AngularJS (phiên bản Angular 1).
ste2425

-1

Trong Angular 7 + ionic 4, nội dung Html có thể được hiển thị bằng cách sử dụng "[InternalHTML]":

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

Tôi hy vọng, điều này cũng sẽ giúp bạn. Cảm ơn.


vui lòng cho tôi biết những gì sai trong mã này là nguyên nhân để tải xuống bài đăng này. Tôi đã kiểm tra mã này trong ứng dụng 2 của tôi. Nó hoạt động. Hãy chia sẻ kinh nghiệm của bạn. Cảm ơn rất nhiều.
Kam Meat

1
AngularJS bằng Angular 1.x. Angular 7 là một khung hoàn toàn khác
Aw Snap
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.