Wstaw HTML do widoku z kontrolera AngularJS


800

Czy można utworzyć fragment HTML w kontrolerze AngularJS i wyświetlić ten HTML w widoku?

Wynika to z konieczności przekształcenia niespójnego obiektu blob JSON w zagnieżdżoną listę id: valuepar. Dlatego HTML jest tworzony w kontrolerze i teraz chcę go wyświetlić.

Utworzyłem właściwość modelu, ale nie mogę tego renderować w widoku bez drukowania tylko kodu HTML .


Aktualizacja

Wygląda na to, że problem wynika z kątowego renderowania utworzonego HTML jako ciąg znaków w cudzysłowie. Spróbuję znaleźć sposób na obejście tego.

Przykładowy kontroler:

var SomeController = function () {

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

Przykładowy widok:

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

Daje:

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

1
Zobacz także to pytanie z pytaniem, czy możliwe jest uruchomienie skryptów we wstawionym HTML.
rejestracja

Czy możliwe jest powiązanie wielu obiektów w tym samym ng-bind? jak `` ng-bind = "site.address_1 site.address_2 site.zip"
fauverism

jeśli masz dużo rzeczy na swojej stronie, będziesz musiał zmienić wiersz 15046 angular.js (szaleństwo) z function htmlSanitizer(html) {.... Angular dev zdecydował, że powinieneś być w stanie znaleźć powiązanie HTML, powoli przeglądając wszystkie ukryte elementy stron jeden po drugim, aby znaleźć JEDEN POJEDYNCZY brakujący fragment HTML. !!! bardzo zły na takie założenie !!!
user3338098,

Przepraszamy, wybrana przez Łukasza odpowiedź może nie być całkowicie poprawną odpowiedzią. Prawidłową odpowiedź można znaleźć w innym pytaniu tutaj . Zasadniczo „ng-bind-html-unsafe renderuje zawartość tylko w formacie HTML. Nie wiąże zakresu Angular z wynikowym DOM. W tym celu należy użyć usługi kompilacji $”.
gm2008,

ng-bind usuwa wszystkie wewnętrzne pliki HTML. a nie tak działa filtr, jest ok, gdy filtr jest jedyną wartością
Muhammad Umer

Odpowiedzi:


1120

W przypadku Angulara 1.x użyj ng-bind-htmlw HTML:

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

W tym momencie pojawi się attempting to use an unsafe value in a safe contextbłąd, więc musisz użyć ngSanitize lub $ sce, aby rozwiązać ten problem.

$ sce

Użyj $sce.trustAsHtml()w kontrolerze, aby przekonwertować ciąg HTML.

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

ngSanitize

Istnieją 2 kroki:

  1. obejmują zasób angular-sanitize.min.js, tj .:
    <script src="lib/angular/angular-sanitize.min.js"></script>

  2. W pliku js (kontroler lub zwykle app.js) dołącz ngSanitize, tj .:
    angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives', 'ngSanitize'])


30
W Angularze 1.2 ng-bind-html-unsafeusunięto i połączono dwie dyrektywy. Zobacz: github.com/angular/angular.js/blob/master/…
Sasha Chedygov

60
Bez użycia ngSanitize można to zrobić teraz, używając $sce. Wciśnij go do kontrolera i prześlij przez niego html. $scope.thisCanBeusedInsideNgBindHtml = $sce.trustAsHtml(someHtmlVar);W przeciwnym razie ciągle dostawałemattempting to use an unsafe value in a safe context
Matsemann,

3
Potrzebujemy tutaj trochę uporządkowania, co jest właściwym sposobem, w którym nic nie działa dla mnie.
wylądował

9
stackoverflow.com/questions/21829275/… <- działało dla mnie :) żadna z opcji w odpowiedzi tutaj nie działa niestety
anpatel

7
Aby ludzie nie byli zniechęceni, najnowsza aktualizacja tej odpowiedzi, w połączeniu z wymaganiem ngSanitize na dole odpowiedzi, faktycznie działa.
Ben Cull,

312

Możesz także utworzyć taki filtr:

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

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

Następnie w widoku

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

Uwaga : Ten filtr ufa każdemu przekazanemu do niego plikowi HTML i może stanowić lukę w zabezpieczeniach XSS, jeśli zostaną przekazane do niego zmienne z danymi wejściowymi użytkownika.


@Katie Astrauskas, dziękuję za odpowiedź! Bardzo czysty sposób. ngResourceZależność BTW nie jest konieczna.
Athlan,

28
Używaj tego tylko wtedy, gdy całkowicie ufasz HTML. Nie dezynfekuje to HTML w żaden sposób, ale pozwala Angularowi na wstrzyknięcie go na stronę. Złośliwy kod HTML może wywoływać ataki XSS.
jan.vdbergh

Jeśli wydajność jest ważna, należy unikać używania filtrów. Filtr wywoła za każdym razem dwa podsumowania.
Tantelope,

14
Dlaczego wywoływany jest filtr sanitize? Jest to tak mylące, że w rzeczywistości niczego nie dezynfekuje. Zamiast tego powinno się nazywać trust, trustSafelub coś podobnego.
Denis Pshenov

1
Cudowna odpowiedź. rawHtmlto moje imię do filtra zamiast sanitize.
Wumms,

119

Angular JS pokazuje HTML w znaczniku

Rozwiązanie podane w powyższym linku działało dla mnie, żadna z opcji w tym wątku nie działała. Dla każdego, kto szuka tego samego w AngularJS w wersji 1.2.9

Oto kopia:

Ok znalazłem rozwiązanie tego:

JS:

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

HTML:

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

EDYTOWAĆ:

Oto konfiguracja:

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

    }]);

Plik HTML:

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

7
Pamiętaj, że musisz być absolutnie pewien, że html może być zaufany. W przeciwnym razie drzwi są szeroko otwarte na ataki XSS.
jan.vdbergh

To rozwiązanie, wykorzystujące funkcję do renderowania HTML, jest jedynym, które działało dla mnie.
MarceloBarbosa

do czego służy $ $ http?
Soldeplata Saketos,

@SoldeplataSaketos nic szczególnego, myślę, że próbowałem w tym czasie lokalnie i ostatecznie skończyłem kopiowanie zależności.
anpatel

Ta sama aktualizacja odpowiedzi tutaj. stackoverflow.com/questions/21829275/…
Surya R Praveen

65

Na szczęście nie potrzebujesz żadnych wymyślnych filtrów ani niebezpiecznych metod, aby uniknąć tego komunikatu o błędzie. Jest to kompletna implementacja umożliwiająca prawidłowe wyświetlanie znaczników HTML w widoku w zamierzony i bezpieczny sposób.

Moduł odkażający musi być dołączony po 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>

Następnie moduł musi zostać załadowany:

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

Umożliwi to dołączenie znaczników do ciągu z kontrolera, dyrektywy itp .:

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

Wreszcie w szablonie należy go wyprowadzić w następujący sposób:

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

Co da oczekiwany wynik: 42 to odpowiedź .


1
Spróbuj html jak <div><label>Why My Input Element Missing</label><input /></div>... Jeśli to cię zaskakuje, to zaktualizuj swoją odpowiedź plz .. Ponieważ przetestowałem wszystkie rozwiązania głosowania 10+. Twoje rozwiązanie nie działało, żeby zobaczyć moje tagi wejściowe .. w przeciwnym razie dobrze ... użyłem$sce.trustAsHtml(html)
Sami

To rozwiązanie działa, chcesz opublikować jsfiddle lub plunkr?
Pier-Luc Gendreau

To naprawdę powinna być odpowiedź, jeśli używasz najnowszego kąta
Sandeep

61

Próbowałem dzisiaj, jedynym sposobem, jaki znalazłem, było to

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


6
Tego rozwiązania należy używać tylko wtedy, gdy źródło jest zaufane, aby uniknąć ataków skryptów krzyżowych.
Bertrand

3
Począwszy od wersji Angular 1.0.2, działa to dla mnie, bez żadnych innych plików ani podłączania.
rejestracja

1
Korzystanie z Angular 1.0.8 i to działało dla mnie. Uważaj jednak na ostrzeżenie Bertranda, upewnij się, że ufasz źródłu.
Jack Slingerland,

12
Dla przyszłego odniesienia ng-bind-html-unsafe został usunięty w wersji 1.2. Teraz potrzebujesz modułu ngSanitize i aby powiązać niebezpieczny HTML, powinieneś użyć metody $ sce.trustAsHtml.
Lucas Lazaro,

53

ng-bind-html-unsafe nie działa.

To jest najkrótsza droga:

Utwórz filtr:

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

I twoim zdaniem:

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

PS Ta metoda nie wymaga dołączania ngSanitizemodułu.


3
To najlepsze rozwiązanie, jakie widziałem tutaj dla Angulara 1.2. Rozwiązanie zastosowane $scew zaakceptowanej odpowiedzi nie działało dla mnie i nie chciałem uwzględniać dodatkowej zależności dla czegoś tak trywialnego.
Daniel Bonnell,

Rozwiązanie Bidhana Bhattarai działało dla mnie. Angular 1.6.1
mediaguru 16.04.17

25

na HTML

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

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

LUB

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

na kontrolerze

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

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

współpracuje również z $scope.comment.msg = $sce.trustAsHtml(html);


1
$scejest schludny, ale czy użytkownik nie może po prostu dodać tutaj punktu przerwania i przywrócić szkodliwy kod do this.myCtrl.comment.msgkorzystania z debugera?
BradGreens

z drugiej strony, BradGreens, czy byłbyś w stanie zrobić to samo z ng-bind-html-niebezpiecznym?
CodeOverRide

4
Jeśli ktoś chce zhakować własną przeglądarkę, może, kogo to obchodzi. Nie wpłynie to na innych użytkowników. @BradGreens Czy to jest pytanie?
Chris Stephens

@Chris Pomaga ci mieć rację. Myślę, że to odpowiada na moje pytanie, ale moim zdaniem te cechy są bliższe postrzeganemu bezpieczeństwu niż prawdziwemu bezpieczeństwu. Być może chroni przed jakimś zautomatyzowanym atakiem? Nigdy nie zrozumiałem, dlaczego robienie takich rzeczy naprawdę pomaga aplikacji. Moja aplikacja musi dodać filtr do KAŻDEJ instancji renderowania wysiwyg HTML, ponieważ może mieć wbudowany CSS, który się ng-bind-htmlrozbiera.
BradGreens

1
Cóż, te funkcje pomagają zmniejszyć liczbę bezpiecznych błędów kodowania. W szczególności problem ze znacznikami / wprowadzaniem kodu. Domyślnie wszystkie powiązane dane są kodowane do wyświetlania. Zasadniczo, jeśli chcesz uzyskać znaczniki wyjściowe, zmusza to do myślenia o tym, co próbujesz zrobić. Bez tych funkcji można wiele zrobić z samym bezpieczeństwem po stronie serwera, ale aby oddzielić obawy, aplikacja klienta powinna prawidłowo obsługiwać dane do wyświetlenia.
Chris Stephens

9

Odkryłem, że użycie ng-sanitize nie pozwoliło mi dodać kliknięcia ng w pliku HTML.

Aby rozwiązać ten problem, dodałem dyrektywę. Lubię to:

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

A to jest HTML:

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

Powodzenia.


6

Właśnie to zrobiłem, używając ngBindHtml, postępując zgodnie z dokumentacją kątową (v1.4) ,

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

Upewnij się, że umieściłeś ngSanitize w zależnościach modułu. To powinno działać dobrze.


4

Innym rozwiązaniem, bardzo podobnym do blrbr's, z wyjątkiem używania atrybutu o zasięgu, jest:

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

I wtedy

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

Uwaga można zastąpić element.append()zelement.replaceWith()


3

istnieje jeszcze jedno rozwiązanie tego problemu, polegające na utworzeniu nowego atrybutu lub dyrektyw w formie kątowej.

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>

lub

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

lub

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

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


3

możesz także użyć ng-include .

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

możesz użyć „ng-show”, aby pokazać ukrywanie danych tego szablonu.


Jesteś pewien, że to wszystko, czego potrzebujesz, aby korzystać z ng-include?
fauweryzm

tak .. wypróbowałem to. a jeśli używasz szablonu, użyj go w następujący sposób - <script type = "text / ng-template" id = "custom.html">
Vikash Sharma

2

oto rozwiązanie zrób taki filtr

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

i zastosuj to jako filtr do ng-bind-html like

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

i dziękuję Rubenowi Decropowi


1

Posługiwać się

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

i

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

W tym celu musisz angular-sanitize.jsna przykład dołączyć do pliku HTML plik

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

0

Oto prosta (i niebezpieczna) bind-as-htmldyrektywa, bez potrzeby ngSanitize:

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

Pamiętaj, że spowoduje to problemy związane z bezpieczeństwem, jeśli powiążą niezaufane treści.

Użyj tak:

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

-1

Przykład roboczy z potokiem do wyświetlania html w szablonie z Angular 4.

1.Ocena rur 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. Zarejestruj potok do app.module.ts

 import {EscapeHtmlPipe} from './components/pipes/escape-html.pipe';
    declarations: [...,EscapeHtmlPipe]
  1. Użyj w swoim szablonie

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

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

    Dodaj odpowiednią implementację dla getDivHtml w powiązanym pliku component.ts.


1
Myślę, że współpracuje z AngularJS, a nie z nowszą wersją.
Trąd

-1

Po prostu proste użycie [innerHTML], jak poniżej:

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

Zanim będziesz musiał użyć ng-bind-html...


Jest to dostępne tylko w Angular (wersja Angular 2+), a nie AngularJS (wersja Angular 1).
ste2425

-1

W Angular 7 + ionic 4 zawartość HTML można wyświetlić za pomocą „[innerHTML]”:

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

Mam nadzieję, że ci to pomoże. Dzięki.


uprzejmie powiedz mi, co jest nie tak w tym kodzie, co powoduje, że głosuję za tym postem. Przetestowałem ten kod w mojej 2 aplikacji. To działa. Podziel się swoim doświadczeniem. Wielkie dzięki.
Kamlesh,

1
AngularJS równa się Angular 1.x. Angular 7 to zupełnie inna platforma
Aw Snap
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.