Вставьте HTML в представление

805

Возможно ли создать фрагмент HTML в контроллере AngularJS и отобразить этот HTML в представлении?

Это связано с требованием превратить несогласованный BLOB-код в вложенный список пар id : value. Поэтому HTML создается в контроллере, и теперь я хочу его отобразить.

Я создал свойство модели, но не могу сделать это в представлении без его просто печати HTML.


Update

Похоже, что проблема возникает из angular рендеринга созданного 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.
  • 0
    Можно ли привязать несколько объектов к одному и тому же ng-bind? как `` `ng-bind =" site.address_1 site.address_2 site.zip "
Показать ещё 3 комментария
Теги:
escaping
html-sanitizing

19 ответов

1031
Лучший ответ

Для 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);

ngSanitize

Есть два шага:

  • включают ресурс angular -sanitize.min.js, т.е.:
    <script src="lib/angular/angular-sanitize.min.js"></script>

  • В файле js (контроллер или обычно app.js) включите ngSanitize, т.е.:
    angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives', 'ngSanitize'])

  • 27
    В Angular 1.2 ng-bind-html-unsafe был удален, и две директивы были объединены. Смотрите: github.com/angular/angular.js/blob/master/…
  • 58
    Без использования ngSanitize это можно сделать сейчас с помощью $sce . Вставьте его в контроллер и пропустите HTML через него. $scope.thisCanBeusedInsideNgBindHtml = $sce.trustAsHtml(someHtmlVar); В противном случае я продолжал attempting to use an unsafe value in a safe context
Показать ещё 15 комментариев
319

Вы также можете создать такой фильтр:

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, если к нему передаются переменные с пользовательским вводом.

  • 0
    @ Кэти Астраускас, спасибо за ответ! Очень чистый способ. КСТАТИ ngResource зависимость не neccesary.
  • 27
    Используйте это только тогда, когда вы полностью доверяете HTML. Это никоим образом не дезинфицирует HTML, а только позволяет Angular внедрить его в страницу. Вредоносный HTML может спровоцировать атаки XSS.
Показать ещё 5 комментариев
121

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>

EDIT:

Здесь настроено:

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.
  • 1
    embed.plnkr.co/gQ2Rrn
Показать ещё 4 комментария
61

Я пробовал сегодня, единственный способ найти это

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

  • 6
    Это решение следует использовать, только если источник заслуживает доверия, чтобы избежать атак межсайтового скриптинга.
  • 3
    Начиная с Angular 1.0.2, это работает для меня, без каких-либо других файлов или подключения требуется.
Показать ещё 3 комментария
60

К счастью, вам не нужны какие-либо причудливые фильтры или небезопасные методы, чтобы избежать этого сообщения об ошибке. Это полная реализация для корректного вывода разметки 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)
  • 0
    Это решение работает, хотите опубликовать jsfiddle или plunkr?
Показать ещё 1 комментарий
49

ng-bind-html-unsafe больше не работает.

Это самый короткий путь:

Создать фильтр:

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

И на ваш взгляд:

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

P.S. Этот метод не требует включения модуля ngSanitize.

  • 2
    Это лучшее решение, которое я видел здесь для Angular 1.2. Решение, использующее $sce в принятом ответе, не сработало для меня, и я не хотел включать дополнительную зависимость для чего-то такого тривиального.
  • 0
    Решение Бидхана Бхаттараи сработало для меня. Угловой 1.6.1
26

на 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 останова и восстановить какой-либо вредоносный код в this.myCtrl.comment.msg с помощью отладчика?
  • 0
    затем снова BradGreens, вы могли бы сделать то же самое с ng-bind-html-unsafe?
Показать ещё 4 комментария
16

Как и в случае с Angular 4, теперь это работает:

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

Взято из этого вопроса здесь.

9

Я обнаружил, что использование ng-sanitize не позволило мне добавить ng-click в html.

Чтобы решить эту проблему, я добавил директиву. Вот так:

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

Просто сделал это с помощью ngBindHtml, выполнив angular (v1.4) docs,

<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" , чтобы показать скрытые данные этого шаблона.

  • 0
    Вы уверены, что это все, что вам нужно сделать, чтобы использовать ng-include?
  • 0
    да .. я попробовал это. и если вы используете шаблон, используйте его следующим образом - <script type = "text / ng-template" id = "custom.html">
2

См. ответы, которые я разместил для вас в этих двух местах:

http://forum.ionicframework.com/t/eval-json-data-as-html/1455/6

http://codepen.io/calendee/pen/DKhbc

1

вот решение сделать фильтр, подобный этому

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

и примените это как фильтр к ng-bind-html, как

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

и спасибо Рубену Decrop

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

Просто используйте [innerHTML], как [innerHTML] ниже:

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

Прежде чем вам нужно было использовать ng-bind-html...

0

Рабочий пример с трубкой для отображения html в шаблоне с угловым 4.

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. Использовать в шаблоне

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

    Добавьте соответствующую реализацию для getDivHtml в файл related.ts.

  • 0
    Я думаю, что он работает с AngularJS, а не с новой версией.
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>

Ещё вопросы

Сообщество Overcoder
Наверх
Меню