Вставте HTML у вигляд від контролера AngularJS


800

Чи можливо створити фрагмент HTML в контролері AngularJS і чи цей HTML відображений у поданні?

Це випливає з вимоги перетворити непослідовну крапку 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 для запуску.
загадка

Чи можливо кілька об'єктів пов'язані в одне ng-bind? на кшталт `` `ng-bind =" site.address_1 site.address_2 site.zip "
fauverism

якщо на вашій сторінці багато матеріалів, вам доведеться змінити рядок 15046 з angular.js (божевілля) function htmlSanitizer(html) {.... Кутовий розробник вирішив, що ви зможете знайти будь-яку html-прив'язку, повільно перебираючи всі ваші сторінки приховані елементи один за одним, щоб знайти, що ОДИН ЄДИН відсутній фрагмент html. !!! дуже злий на таке припущення !!!
користувач3338098

Вибачте, обрана Лука відповідь може бути не зовсім правильною відповіддю. Правильну відповідь можна знайти в іншому запитанні тут . В основному, "ng-bind-html-unsafe надає вміст лише у вигляді HTML. Він не пов'язує кутовий діапазон із результатом DOM. Для цього потрібно використовувати службу $ compile."
gm2008

ng-bind видаляє всі внутрішні HTML-файли. який не працює як фільтр, це нормально, коли фільтр є єдиним значенням
Мухаммед Умер

Відповіді:


1120

Для кутового 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.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'])


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


@Katie Astrauskas, дякую за відповідь! Дуже чистий спосіб. ДО РЕЧІ ngResourceзалежність не neccesary.
Атлан

28
Використовуйте це лише тоді, коли ви повністю довіряєте HTML. Це жодним чином не санітує HTML, а лише дозволяє Angular вводити його у сторінку. Шкідливий HTML може спровокувати атаки XSS.
jan.vdbergh

Якщо продуктивність важлива, вам слід уникати використання фільтрів. Фільтр буде спровокувати дві дайджести щоразу.
Тантелопа

14
Чому називається фільтр sanitize? Це настільки оману, що насправді нічого не санітує. Натомість його слід називати trust, trustSafeчи щось подібне.
Денис Пшенов

1
Чудова відповідь. rawHtmlце моє ім'я для фільтра замість sanitize.
Wumms

119

Кутовий JS показує HTML у тезі

Рішення, подане у наведеному вище посиланні, працювало для мене, жоден із варіантів цього потоку не робив. Для тих, хто шукає те саме, що з версією 1.2.2

Ось копія:

Гаразд, я знайшов рішення для цього:

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/…
Surya R

65

На щастя, для уникнення цього повідомлення про помилку вам не потрібні модні фільтри чи небезпечні методи. Це повна реалізація для правильного виведення розмітки HTML у представленні призначеним та безпечним способом.

Модуль санітарії повинен бути включений після кутового:

<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>... Якщо це здивує, то оновіть свою відповідь plz .. Тому що я перевірив усі 10 + голосових рішень .. Ваше рішення не працювало для мене, щоб побачити мої вхідні теги .. нормально інакше .. я мав використовувати$sce.trustAsHtml(html)
Самі

Це рішення працює, хочете опублікувати jsfiddle або plunkr?
П’єр-Люк Джендро

Це дійсно має бути відповіддю, якщо використовувати останній кутовий
Sandeep

61

Я спробував сьогодні, єдиний спосіб, який я знайшов, це було

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


6
Це рішення слід використовувати лише за умови довіри джерела, щоб уникнути міжсайтових сценаріїв.
Бертран

3
Станом на Angular 1.0.2, це працює для мене, не потребуючи інших файлів чи пошуку.
загадка

1
Використовуючи Angular 1.0.8, і це працювало для мене. Попередьте, будь ласка, попередьте джерело.
Джек Слінгерланд

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у прийнятій відповіді, для мене не спрацювало, і я не хотів включати додаткову залежність від чогось такого тривіального.
Даніель Боннелл

На мене працювало рішення Бідхана Бхаттараї. 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

то знову ж таки, BradGreens, чи зможете ви зробити те ж саме і з ng-bind-html-небезпечним?
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, за винятком використання атрибута масштабування:

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

є ще одне рішення цієї проблеми за допомогою створення нового атрибута або директив у кутовій.

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?
фауризм

так .. я спробував це. а якщо ви використовуєте шаблон, то використовуйте його наступним чином - <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

Робочий приклад з трубою для відображення 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 у пов'язаний файл компонент.ts.


1
Я думаю, що він працює з AngularJS, а не з новою версією.
Проказа

-1

Просто просте використання [innerHTML], як нижче:

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

Перш ніж вам потрібно було користуватися ng-bind-html...


Це доступно лише у кутових (кутова версія 2+), а не у AngularJS (кутова версія 1).
ste2425

-1

У Angular 7 + ionic 4 вміст Html може бути показаний за допомогою "[innerHTML]":

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

Сподіваюся, це теж допоможе вам. Дякую.


ласкаво скажи мені, що не так у цьому коді, що є причиною заборонити цю посаду. Я перевірив цей код у своїй програмі 2. Це працює. Будь ласка, поділіться своїм досвідом. Дуже дякую.
Kamlesh

1
AngularJS дорівнює кутовому 1.x. Angular 7 - це зовсім інші рамки
Aw Snap
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.