Inserisci HTML in vista dal controller AngularJS


800

È possibile creare un frammento HTML in un controller AngularJS e mostrare questo HTML nella vista?

Ciò deriva dall'obbligo di trasformare un BLOB JSON incoerente in un elenco nidificato di id: valuecoppie. Pertanto, l' HTML viene creato nel controller e ora sto cercando di visualizzarlo.

Ho creato una proprietà del modello, ma non posso renderlo nella vista senza che stampi semplicemente l' HTML .


Aggiornare

Sembra che il problema derivi dal rendering angolare dell'HTML creato come stringa tra virgolette. Tenterà di trovare un modo per aggirare questo.

Esempio di controller:

var SomeController = function () {

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

Vista di esempio:

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

Dà:

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

1
Vedi anche questa domanda , chiedendo se è possibile ottenere script in HTML inserito per l'esecuzione.
enigment

È possibile avere più oggetti associati allo stesso ng-bind? come `` `ng-bind =" site.address_1 site.address_2 site.zip "
fauverism

se hai molte cose sulla tua pagina dovrai modificare la riga 15046 di angular.js (follia) di function htmlSanitizer(html) {.... Gli sviluppatori angolari hanno deciso che dovresti essere in grado di trovare qualsiasi associazione html esaminando lentamente tutte le tue pagine gli elementi nascosti uno a uno per trovare quel SOLO pezzo mancante di html. !!! molto arrabbiato per un tale presupposto !!!
user3338098,

Spiacenti, la risposta scelta da Luke potrebbe non essere la risposta totalmente giusta. La risposta giusta può essere trovata in un'altra domanda qui . Fondamentalmente, "ng-bind-html-unsafe rende il contenuto solo in formato HTML. Non vincola l'ambito angolare al DOM risultante. Devi usare il servizio $ compile per quello scopo."
gm2008 del

ng-bind rimuove tutto l'html interno. che non è come il filtro funzionerebbe, va bene quando il filtro è l'unico valore
Muhammad Umer

Risposte:


1120

Per Angular 1.x, utilizzare ng-bind-htmlin HTML:

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

A questo punto si otterrebbe un attempting to use an unsafe value in a safe contexterrore, quindi è necessario utilizzare ngSanitize o $ sce per risolverlo.

$ sce

Utilizzare $sce.trustAsHtml()nel controller per convertire la stringa html.

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

ngSanitize

Ci sono 2 passaggi:

  1. include la risorsa angular-sanitize.min.js, ovvero:
    <script src="lib/angular/angular-sanitize.min.js"></script>

  2. In un file js (controller o di solito app.js), includere ngSanitize, ovvero:
    angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives', 'ngSanitize'])


30
In Angular 1.2, è ng-bind-html-unsafestato rimosso e le due direttive sono state combinate. Vedi: github.com/angular/angular.js/blob/master/…
Sasha Chedygov

60
Senza usare ngSanitize, ora puoi farlo usando $sce. Inseriscilo nel controller e passaci attraverso l'html. $scope.thisCanBeusedInsideNgBindHtml = $sce.trustAsHtml(someHtmlVar);Altrimenti continuavo a ricevereattempting to use an unsafe value in a safe context
Matsemann il

3
Abbiamo bisogno di un po 'di pulizia qui, che è il modo giusto che nulla sembra funzionare per me.
sbarcò il

9
stackoverflow.com/questions/21829275/… <- ha funzionato per me :) nessuna delle opzioni nelle risposte qui ha funzionato sfortunatamente
anpatel

7
Proprio così le persone non sono scoraggiate, l'ultimo aggiornamento di questa risposta, insieme al requisito ngSanitize in fondo alla risposta, funziona davvero.
Ben Cull,

312

Puoi anche creare un filtro in questo modo:

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

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

Quindi nella vista

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

Nota : questo filtro si fida di tutti gli html trasmessi e potrebbe presentare una vulnerabilità XSS se gli vengono passate variabili con input dell'utente.


@ Katie Astrauskas, grazie per la risposta! Modo molto pulito. La ngResourcedipendenza BTW non è necessaria.
Athlan

28
Utilizzalo solo quando ti fidi completamente dell'HTML. Questo non igienizza l'HTML in alcun modo, ma consente solo ad Angular di iniettarlo nella pagina. HTML dannoso può provocare attacchi XSS.
Jan.vdbergh,

Se le prestazioni sono importanti, dovresti evitare l'uso di filtri. Un filtro attiverà due digest ogni volta.
Tantelope,

14
Perché viene chiamato il filtro sanitize? Questo è così fuorviante in quanto non igienizza nulla. Invece dovrebbe essere chiamato trust, trustSafeo qualcosa di simile.
Denis Pshenov,

1
Risposta meravigliosa rawHtmlè il mio nome per il filtro anziché sanitize.
Wumms,

119

JS angolare mostra HTML all'interno del tag

La soluzione fornita nel link sopra ha funzionato per me, nessuna delle opzioni su questo thread ha funzionato. Per tutti coloro che cercano la stessa cosa con AngularJS versione 1.2.9

Ecco una copia:

Ok ho trovato la soluzione per questo:

JS:

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

HTML:

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

MODIFICARE:

Ecco la configurazione:

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

    }]);

File HTML:

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

7
Tieni presente che devi essere assolutamente sicuro che l'html possa essere attendibile. Altrimenti la porta è spalancata per gli attacchi XSS.
Jan.vdbergh,

Questa soluzione, usando una funzione per rendere l'HTML, è l'unica che ha funzionato per me.
MarceloBarbosa,

a cosa serve il '$ http'?
Soldeplata Saketos,

@SoldeplataSaketos niente in particolare, penso che stavo provando localmente in quel momento e ho finito per copiare la dipendenza.
Anpatel,

Aggiornamento della stessa risposta qui. stackoverflow.com/questions/21829275/…
Surya R Praveen

65

Fortunatamente, non è necessario alcun filtro di fantasia o metodi non sicuri per evitare quel messaggio di errore. Questa è l'implementazione completa per l'output corretto del markup HTML in una vista nel modo previsto e sicuro.

Il modulo di sanificazione deve essere incluso dopo Angolare:

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

Quindi, il modulo deve essere caricato:

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

Ciò ti consentirà di includere il markup in una stringa da un controller, direttiva, ecc:

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

Infine, in un modello, deve essere prodotto in questo modo:

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

Il che produrrà il risultato atteso: 42 è la risposta .


1
Prova alcuni html come <div><label>Why My Input Element Missing</label><input /></div>... Se ti sorprende, allora aggiorna la tua risposta per favore .. Perché ho testato tutte le 10 + soluzioni di voto .. La tua soluzione non ha funzionato per me per vedere i miei tag di input .. bene altrimenti .. Ho usato$sce.trustAsHtml(html)
Sami,

Questa soluzione funziona, ti interessa pubblicare un jsfiddle o un plunkr?
Pier-Luc Gendreau,

Questa dovrebbe davvero essere la risposta se si utilizza l'ultima angolare
Sandeep,

61

Ho provato oggi, l'unico modo che ho trovato è stato questo

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


6
Questa soluzione dovrebbe essere utilizzata solo se l'origine è attendibile per evitare attacchi di scripting tra siti.
Bertrand,

3
A partire da Angular 1.0.2, questo funziona per me, senza altri file o collegamenti richiesti.
enigment

1
Usando Angular 1.0.8 e questo ha funzionato per me. Fai attenzione all'avvertimento di Bertrand, assicurati di fidarti della fonte.
Jack Slingerland,

12
Per riferimento futuro ng-bind-html-unsafe è stato rimosso nella versione 1.2. Ora hai bisogno del modulo ngSanitize e per associare html non sicuro devi usare il metodo $ sce.trustAsHtml.
Lucas Lazaro,

53

ng-bind-html-unsafe non lavora più.

Questo è il modo più breve:

Crea un filtro:

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

E a tuo avviso:

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

PS Questo metodo non richiede di includere il ngSanitizemodulo.


3
Questa è la migliore soluzione che ho visto qui per Angular 1.2. La soluzione utilizzata $scenella risposta accettata non ha funzionato per me e non volevo includere una dipendenza aggiuntiva per qualcosa di così banale.
Daniel Bonnell,

La soluzione di Bidhan Bhattarai ha funzionato per me. Angolare 1.6.1
mediaguru

25

su html

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

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

O

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

sul controller

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

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

funziona anche con $scope.comment.msg = $sce.trustAsHtml(html);


1
$sceè pulito ma un utente non può semplicemente aggiungere un punto di interruzione qui e ripristinare qualsiasi codice dannoso this.myCtrl.comment.msgutilizzando un debugger?
BradGreens,

poi di nuovo BradGreens, saresti in grado di fare lo stesso anche con ng-bind-html-unsafe?
CodeOverRide,

4
Se qualcuno vuole hackerare il proprio browser può farlo, chi se ne frega. Non avrà alcun effetto sugli altri utenti. @BradGreens È questa la domanda?
Chris Stephens,

@ChrisStephens hai ragione. Immagino che risponda alla mia domanda, ma la mia opinione è che queste funzionalità sono più vicine alla sicurezza percepita che alla sicurezza reale. Forse protegge da una sorta di attacchi automatici? Non ho mai capito chiaramente perché fare queste cose aiuta davvero l'app. La mia app deve aggiungere un filtro a OGNI istanza di rendering HTML wysiwyg perché potrebbe avere CSS incorporato, che viene ng-bind-htmlrimosso.
BradGreens,

1
Bene, queste funzionalità aiutano a ridurre gli errori di codifica sicuri. In particolare il problema con l'iniezione markup / codice. Per impostazione predefinita, tutti i dati associati sono codificati per la visualizzazione. Quindi, fondamentalmente, se si desidera generare un markup, questo ti costringe a pensare a ciò che stai cercando di fare. Senza queste funzionalità puoi fare molto con la sola sicurezza lato server, ma per separare le preoccupazioni l'app client dovrebbe incaricare di gestire correttamente i dati per la visualizzazione.
Chris Stephens,

9

Ho scoperto che l'uso di ng-sanitize non mi ha permesso di aggiungere ng-click nell'html.

Per risolvere questo ho aggiunto una direttiva. Come questo:

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

E questo è l'HTML:

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

In bocca al lupo.


6

Ho appena fatto questo usando ngBindHtml seguendo documenti angolari (v1.4) ,

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

Assicurati di includere ngSanitize nelle dipendenze del modulo. Quindi dovrebbe funzionare bene.


4

Un'altra soluzione, molto simile a quella di blrbr, tranne per l'uso di un attributo con ambito è:

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

E poi

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

Nota che è possibile sostituire element.append()conelement.replaceWith()


3

esiste un'altra soluzione per questo problema utilizzando la creazione di nuovi attributi o direttive in angolare.

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>

o

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

o

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

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


3

puoi anche usare ng-include .

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

puoi usare "ng-show" per mostrare nascondi i dati di questo modello.


Sei sicuro che questo è tutto ciò che devi fare per usare ng-include?
fauverism

si .. l'ho provato. e se stai usando il template, usalo nel modo seguente - <script type = "text / ng-template" id = "custom.html">
Vikash Sharma,

2

ecco la soluzione crea un filtro come questo

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

e applicalo come filtro a ng-bind-html come

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

e grazie a Ruben Decrop


1

Uso

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

e

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

Per questo, è necessario includere angular-sanitize.js, ad esempio, nel file html con

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

0

Ecco una bind-as-htmldirettiva semplice (e non sicura) , senza la necessità di ngSanitize:

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

Si noti che ciò si aprirà per problemi di sicurezza, se si associa il contenuto non attendibile.

Usa così:

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

-1

Esempio di funzionamento con pipe per visualizzare HTML nel modello con Angular 4.

1.Crate 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. Registrare pipe su app.module.ts

 import {EscapeHtmlPipe} from './components/pipes/escape-html.pipe';
    declarations: [...,EscapeHtmlPipe]
  1. Usa nel tuo modello

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

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

    Aggiungi l'implementazione appropriata per getDivHtml nel file component.ts associato.


1
Penso che stia lavorando con AngularJS, non con la versione più recente.
Lebbra

-1

Solo un semplice utilizzo [innerHTML], come di seguito:

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

Prima di dover usare ng-bind-html...


Questo è disponibile solo in Angular (versione angolare 2+), non AngularJS (versione angolare 1).
ste2425

-1

In Angular 7 + ionic 4, i contenuti HTML possono essere mostrati usando "[innerHTML]":

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

Spero che questo ti possa aiutare. Grazie.


gentilmente dimmi cosa c'è di sbagliato in questo codice che è causa di sottovalutare questo post. Ho testato questo codice nella mia 2 applicazione. Funziona. Per favore, condividi la tua esperienza. Molte grazie.
Kamlesh

1
AngularJS è uguale a Angular 1.x. Angular 7 è un framework completamente diverso
Aw Snap il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.