Вставьте HTML в вид из контроллера AngularJS


800

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

Это связано с требованием превратить несовместимый BLOB-объект JSON во вложенный список 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>

1
Также посмотрите этот вопрос , спрашивая, можно ли запустить скрипты во вставленном HTML.
Enigment

Можно ли привязать несколько объектов к одному и тому же ng-bind? как `` `ng-bind =" site.address_1 site.address_2 site.zip "
фоверизм

если у вас есть много материала на вашей странице, вам придется изменить строку 15046 в angular.js (безумие) of function htmlSanitizer(html) {.... Angular Dev's решила, что вы должны быть в состоянии найти любую привязку html, медленно просматривая все свои страницы скрытые элементы один за другим, чтобы найти этот ОДИН ОДИН РАЗ недостающий фрагмент html. !!! очень зол на такое предположение !!!
user3338098

Извините, выбранный ответ Люка может быть не совсем правильным. Правильный ответ можно найти в другом вопросе здесь . По сути, «ng-bind-html-unsafe отображает только контент как HTML. Он не привязывает область видимости Angle к полученному DOM. Для этой цели вы должны использовать сервис $ compile».
gm2008

ng-bind удаляет все внутренние html. это не то, как фильтр будет работать, это нормально, когда фильтр является единственным значением
Мухаммед Умер

Ответы:


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

ngSanitize

Есть 2 шага:

  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/…
Саша Чедыгов

60
Без использования ngSanitize это можно сделать сейчас с помощью $sce. Вставьте его в контроллер и пропустите HTML через него. $scope.thisCanBeusedInsideNgBindHtml = $sce.trustAsHtml(someHtmlVar);В противном случае я продолжал получатьattempting to use an unsafe value in a safe context
Мацеманн

3
Нам нужна небольшая зачистка, которая является правильным способом, который, кажется, ничего не работает для меня.
приземлился

9
stackoverflow.com/questions/21829275/… <- сработало для меня :) ни один из вариантов в ответах здесь к сожалению не сработал
anpatel

7
Чтобы люди не унывали, последнее обновление этого ответа в сочетании с требованием ngSanitize внизу ответа действительно работает.
Бен Калл

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


@ Кэти Астраускас, спасибо за ответ! Очень чистый способ. Кстати, ngResourceзависимость не обязательна.
Атлан

28
Используйте это только тогда, когда вы полностью доверяете HTML. Это никоим образом не дезинфицирует HTML, а только позволяет Angular внедрить его в страницу. Вредоносный HTML может спровоцировать атаки XSS.
Jan.vdbergh

Если важна производительность, вам следует избегать использования фильтров. Фильтр будет запускать два дайджеста каждый раз.
Tantelope

14
Почему фильтр называется sanitize? Это так вводит в заблуждение, что фактически ничего не дезинфицирует. Вместо этого его следует назвать trust, trustSafeили что - то подобное.
Денис Пшенов

1
Прекрасный ответ. rawHtmlмое имя для фильтра вместо sanitize.
Wumms

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

Это решение, использующее функцию для рендеринга HTML, является единственным, которое работает для меня.
MarceloBarbosa

Для чего нужен $ http?
Soldeplata Saketos

@SoldeplataSaketos ничего особенного, я думаю, что в то время я пробовал это локально, и я закончил копирование зависимости.
anpatel

Тот же ответ обновите здесь. stackoverflow.com/questions/21829275/…
Сурья Р. Правин

65

К счастью, вам не нужны никакие причудливые фильтры или небезопасные методы, чтобы избежать этого сообщения об ошибке. Это полная реализация для правильного и безопасного вывода 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 является ответом .


1
Попробуйте html, например <div><label>Why My Input Element Missing</label><input /></div>... Если вас это удивит, обновите ваш ответ, плз .. Потому что я протестировал все решения с 10 голосами ... Ваше решение не помогло мне увидеть мои входные теги ... отлично, в противном случае ... Я использовал$sce.trustAsHtml(html)
Сами

Это решение работает, хотите опубликовать jsfiddle или plunkr?
Пьер-Люк Жандро

Это действительно должно быть ответом, если использовать последний угловой
Sandeep

61

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

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


6
Это решение следует использовать, только если источник заслуживает доверия, чтобы избежать атак межсайтового скриптинга.
Бертран

3
Начиная с Angular 1.0.2, это работает для меня, без каких-либо других файлов или подключения требуется.
Enigment

1
Используя Angular 1.0.8, и это сработало для меня. Обратите внимание на предостережение @ Бертрана, но убедитесь, что вы доверяете источнику.
Джек Слингерленд,

12
Для дальнейшего использования ng-bind-html-unsafe был удален в версии 1.2. Теперь вам нужен модуль 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в принятом ответе, не сработало для меня, и я не хотел включать дополнительную зависимость для чего-то такого тривиального.
Даниэль Боннелл

Решение Бидхана Бхаттараи сработало для меня. Angular 1.6.1
медиагуру

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

затем снова BradGreens, вы могли бы сделать то же самое с ng-bind-html-unsafe?
CodeOverRide

4
Если кто-то хочет взломать там собственный браузер, он может, кого это волнует. Это не повлияет на других пользователей. @BradGreens Это вопрос?
Крис Стивенс

@ChrisStephens ты прав. Я думаю, это отвечает на мой вопрос, но я считаю, что эти функции ближе к предполагаемой безопасности, чем к реальной безопасности. Возможно, это защищает от каких-то автоматических атак? Я никогда не понимал, почему эти вещи действительно помогают приложению. Мое приложение должно добавить фильтр к КАЖДОМУ экземпляру рендеринга wysiwyg HTML, потому что он может иметь встроенный CSS, который ng-bind-htmlудаляется.
BradGreens

1
Эти функции помогают уменьшить количество ошибок безопасного кодирования. В частности, проблема с разметкой / внедрением кода. По умолчанию все связанные данные кодируются для отображения. В общем, если вы хотите вывести разметку, это заставляет задуматься о том, что вы пытаетесь сделать. Без этих функций вы можете многое сделать только с помощью защиты на стороне сервера, но для разделения проблем клиентское приложение должно взять на себя ответственность за правильную обработку данных для отображения.
Крис Стивенс

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, следуя угловым (v1.4) документам ,

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

продукт-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?
Фоверизм

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

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

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

1.Crated Труба 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 в связанный файл component.ts.


1
Я думаю, что он работает с AngularJS, а не с новой версией.
проказа

-1

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

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

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


Это доступно только в Angular (Angular версия 2+), но не AngularJS (Angular версия 1).
ste2425

-1

В Angular 7 + ionic 4 содержимое Html может быть показано с помощью «[innerHTML]»:

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

Я надеюсь, это также поможет вам. Спасибо.


пожалуйста, скажите мне, что не так в этом коде, который является причиной понизить этот пост. Я проверил этот код в моем приложении 2. Оно работает. Пожалуйста, поделитесь своим опытом. Большое спасибо.
Kamlesh

1
AngularJS равен Angular 1.x. Angular 7 - это совершенно другой фреймворк
Aw Snap
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.