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>
Swaff
źródło
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'])

Luke Madera
źródło
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
źródło
@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>
anpatel
źródło
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ź .

Pier-Luc Gendreau
źródło
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>

Damax
źródło
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.

Bidhan Bhattarai
źródło
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);

Sotos
źródło
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.

Matt
źródło
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.

Henry Neo
źródło
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()

abbaf33f
źródło
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

yugi
źródło
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.

Vikash Sharma
źródło
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

bahri noredine
źródło
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>
Patricia Heimfarth
źródło
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>

źródło
-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.

Sagar Misal
źródło
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...

Alireza
źródło
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.

Kamlesh
źródło
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