Insérer du HTML dans la vue du contrôleur AngularJS

800

Est-il possible de créer un fragment HTML dans un contrôleur AngularJS et d'avoir ce HTML affiché dans la vue?

Cela provient de l'obligation de transformer un blob JSON incohérent en une liste imbriquée de id: valuepaires. Par conséquent, le code HTML est créé dans le contrôleur et je cherche maintenant à l'afficher.

J'ai créé une propriété de modèle, mais je ne peux pas la rendre dans la vue sans imprimer simplement le code HTML .


Mise à jour

Il semble que le problème résulte du rendu angulaire du code HTML créé sous forme de chaîne entre guillemets. J'essaierai de trouver un moyen de contourner cela.

Exemple de contrôleur:

var SomeController = function () {

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

Exemple de vue:

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

Donne:

<div>
    "<ul><li>render me please</li></ul>"
</div>
Swaff
la source
1
Veuillez également consulter cette question , demandant s'il est possible d'obtenir des scripts en HTML inséré à exécuter.
inscription
Est-il possible d'avoir plusieurs objets liés au même ng-bind? comme `` `ng-bind =" site.address_1 site.address_2 site.zip "
fauverisme
si vous avez beaucoup de choses sur votre page, vous devrez modifier la ligne 15046 de angular.js (folie) de function htmlSanitizer(html) {.... Les développeurs angulaires ont décidé que vous devriez être en mesure de trouver n'importe quelle liaison html en parcourant lentement toutes vos pages les éléments cachés un par un pour trouver cette seule pièce manquante de html. !!! très en colère contre une telle hypothèse !!!
user3338098
Désolé, la réponse choisie par Luke n'est peut-être pas la bonne réponse. La bonne réponse peut être trouvée dans une autre question ici . Fondamentalement, "ng-bind-html-unsafe rend uniquement le contenu au format HTML. Il ne lie pas la portée angulaire au DOM résultant. Vous devez utiliser le service $ compile à cette fin."
gm2008
ng-bind supprime tout le html interne. ce qui n'est pas la façon dont le filtre fonctionnerait, c'est correct quand le filtre est la seule valeur
Muhammad Umer

Réponses:

1120

Pour Angular 1.x, utilisez ng-bind-htmldans le HTML:

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

À ce stade, vous obtiendrez une attempting to use an unsafe value in a safe contexterreur, vous devez donc utiliser ngSanitize ou $ sce pour résoudre ce problème.

$ sce

Utilisez $sce.trustAsHtml()dans le contrôleur pour convertir la chaîne html.

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

ngSanitize

Il y a 2 étapes:

  1. inclure la ressource angular-sanitize.min.js, c'est-à-dire:
    <script src="lib/angular/angular-sanitize.min.js"></script>

  2. Dans un fichier js (contrôleur ou généralement app.js), incluez ngSanitize, c'est-à-dire:
    angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives', 'ngSanitize'])

Luke Madera
la source
30
Dans Angular 1.2, a ng-bind-html-unsafeété supprimé et les deux directives ont été combinées. Voir: github.com/angular/angular.js/blob/master/…
Sasha Chedygov
60
Sans utiliser ngSanitize, cela peut être fait maintenant en utilisant $sce. Injectez-le dans le contrôleur et passez-y le HTML. $scope.thisCanBeusedInsideNgBindHtml = $sce.trustAsHtml(someHtmlVar);Sinon, je n'arrêtais pas de recevoirattempting to use an unsafe value in a safe context
Matsemann
3
Nous avons besoin d'un peu de nettoyage ici, ce qui est la bonne façon que rien ne semble fonctionner pour moi.
atterri
9
stackoverflow.com/questions/21829275/… <- a fonctionné pour moi :) aucune des options dans les réponses ici
n'a
7
Juste pour que les gens ne soient pas découragés, la dernière mise à jour de cette réponse, couplée à l'exigence ngSanitize au bas de la réponse, fonctionne en fait.
Ben Cull
312

Vous pouvez également créer un filtre comme ceci:

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

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

Puis dans la vue

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

Remarque : ce filtre approuve tout le code HTML qui lui est transmis et pourrait présenter une vulnérabilité XSS si des variables avec une entrée utilisateur lui sont transmises.

Katie Astrauskas
la source
@Katie Astrauskas, merci pour la réponse! Manière très propre. La ngResourcedépendance BTW n'est pas nécessaire.
Athlan
28
Utilisez-le uniquement lorsque vous faites entièrement confiance au HTML. Cela ne nettoie en aucun cas le code HTML, mais permet uniquement à Angular de l'injecter dans la page. Un code HTML malveillant peut provoquer des attaques XSS.
jan.vdbergh
Si les performances sont importantes, vous devez éviter d'utiliser des filtres. Un filtre déclenchera à chaque fois deux résumés.
Tantelope
14
Pourquoi le filtre est-il appelé sanitize? C'est tellement trompeur qu'il ne désinfecte rien. Au lieu de cela, il doit être appelé trust, trustSafeou quelque chose de similaire.
Denis Pshenov
1
Magnifique réponse. rawHtmlest mon nom pour le filtre au lieu de sanitize.
Wumms
119

Angular JS affiche HTML dans la balise

La solution fournie dans le lien ci-dessus a fonctionné pour moi, aucune des options de ce fil n'a fonctionné. Pour tous ceux qui recherchent la même chose avec AngularJS version 1.2.9

En voici une copie:

Ok j'ai trouvé une solution pour ça:

JS:

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

HTML:

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

ÉDITER:

Voici la configuration:

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

    }]);

Fichier HTML:

<div ng-controller="MyController">
    <div ng-bind-html="renderHtml(body)"></div>
</div>
anpatel
la source
7
Sachez que vous devez être absolument sûr que le html peut être approuvé. Sinon, la porte est grande ouverte pour les attaques XSS.
jan.vdbergh
Cette solution, utilisant une fonction pour rendre le HTML, est la seule qui a fonctionné pour moi.
MarceloBarbosa
à quoi sert le «$ http»?
Soldeplata Saketos
@SoldeplataSaketos rien de particulier, je pense que je l'essayais localement à l'époque et j'ai fini par copier la dépendance.
anpatel
Mise à jour de la même réponse ici. stackoverflow.com/questions/21829275/…
Surya R Praveen
65

Heureusement, vous n'avez pas besoin de filtres sophistiqués ou de méthodes dangereuses pour éviter ce message d'erreur. Il s'agit de l'implémentation complète pour sortir correctement le balisage HTML dans une vue de la manière voulue et sûre.

Le module de désinfection doit être inclus après 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>

Ensuite, le module doit être chargé:

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

Cela vous permettra d'inclure du balisage dans une chaîne à partir d'un contrôleur, d'une directive, etc.:

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

Enfin, dans un modèle, il doit être sorti comme suit:

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

Ce qui produira la sortie attendue: 42 est la réponse .

Pier-Luc Gendreau
la source
1
Essayez du HTML comme <div><label>Why My Input Element Missing</label><input /></div>... Si cela vous surprend, mettez à jour votre réponse plz .. Parce que j'ai testé toutes les solutions de vote + 10 .. Votre solution n'a pas fonctionné pour moi pour voir mes balises d'entrée .. bien sinon .. J'avais utilisé$sce.trustAsHtml(html)
Sami
Cette solution fonctionne, vous voulez poster un jsfiddle ou un plunkr?
Pier-Luc Gendreau le
Cela devrait vraiment être la réponse si vous utilisez la dernière version angulaire
Sandeep
61

J'ai essayé aujourd'hui, le seul moyen que j'ai trouvé était

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

Damax
la source
6
Cette solution ne doit être utilisée que si la source est fiable pour éviter les attaques de script intersite.
Bertrand
3
Depuis Angular 1.0.2, cela fonctionne pour moi, sans aucun autre fichier ou raccordement requis.
inscription
1
Utiliser Angular 1.0.8 et cela a fonctionné pour moi. Tenez compte de l'avertissement de Bertrand cependant, assurez-vous de faire confiance à la source.
Jack Slingerland
12
Pour référence future, ng-bind-html-unsafe a été supprimé dans la version 1.2. Maintenant, vous avez besoin du module ngSanitize et pour lier du HTML non sécurisé, vous devez utiliser la méthode $ sce.trustAsHtml.
Lucas Lazaro
53

ng-bind-html-unsafe ne fonctionne plus.

C'est le chemin le plus court:

Créez un filtre:

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

Et selon vous:

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

PS Cette méthode ne vous oblige pas à inclure le ngSanitizemodule.

Bidhan Bhattarai
la source
3
C'est la meilleure solution que j'ai vue ici pour Angular 1.2. La solution utilisant $scedans la réponse acceptée ne fonctionnait pas pour moi et je ne voulais pas inclure une dépendance supplémentaire pour quelque chose d'aussi trivial.
Daniel Bonnell
La solution de Bidhan Bhattarai a fonctionné pour moi. Angular 1.6.1
mediaguru
25

sur html

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

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

OU

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

sur le contrôleur

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

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

fonctionne aussi avec $scope.comment.msg = $sce.trustAsHtml(html);

Sotos
la source
1
$sceest soigné mais un utilisateur ne pourrait-il pas simplement ajouter un point d'arrêt ici et restaurer un code malveillant à l' this.myCtrl.comment.msgaide d'un débogueur?
BradGreens
encore une fois BradGreens, seriez-vous en mesure de faire de même avec ng-bind-html-unsafe?
CodeOverRide
4
Si quelqu'un veut pirater son propre navigateur, il peut s'en soucier. Cela n'affectera pas les autres utilisateurs. @BradGreens Est-ce la question?
Chris Stephens
@ChrisStephens vous avez raison. Je suppose que cela répond à ma question, mais mon opinion est que ces fonctionnalités sont plus proches de la sécurité perçue que de la sécurité réelle. Peut-être qu'il protège contre une sorte d'attaques automatisées? Je n'ai jamais clairement compris pourquoi faire ces choses aide vraiment l'application. Mon application doit ajouter un filtre à CHAQUE instance de rendu HTML wysiwyg car elle pourrait avoir du CSS en ligne, ce qui ng-bind-htmlse retire.
BradGreens
1
Eh bien, ces fonctionnalités aident à réduire les erreurs de codage sécurisé. En particulier le problème avec le balisage / injection de code. Par défaut, toutes les données liées sont codées pour l'affichage. Donc, fondamentalement, si vous souhaitez générer un balisage, cela vous oblige à réfléchir à ce que vous essayez de faire. Sans ces fonctionnalités, vous pouvez faire beaucoup avec la sécurité côté serveur uniquement, mais pour séparer les préoccupations, l'application cliente devrait facturer la gestion correcte des données pour l'affichage.
Chris Stephens
9

J'ai trouvé que l'utilisation de ng-sanitize ne me permettait pas d'ajouter ng-click dans le html.

Pour résoudre ce problème, j'ai ajouté une directive. Comme ça:

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

Et voici le HTML:

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

Bonne chance.

Mat
la source
6

Je viens de le faire en utilisant ngBindHtml en suivant des documents angulaires (v1.4) ,

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

Assurez-vous d'inclure ngSanitize dans les dépendances du module. Ensuite, cela devrait fonctionner correctement.

Henry Neo
la source
4

Une autre solution, très similaire à celle de blrbr, sauf en utilisant un attribut de portée est:

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

Et alors

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

Notez que vous pouvez remplacer element.append()parelement.replaceWith()

abbaf33f
la source
3

il existe une autre solution à ce problème en utilisant la création de nouveaux attributs ou directives en angulaire.

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>

ou

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

ou

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

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

yugi
la source
3

vous pouvez également utiliser ng-include .

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

vous pouvez utiliser "ng-show" pour afficher masquer ces données de modèle.

Vikash Sharma
la source
Vous êtes sûr que c'est tout ce que vous devez faire pour utiliser ng-include?
fauverisme
oui .. je l'ai essayé. et si vous utilisez un modèle, utilisez-le de la manière suivante - <script type = "text / ng-template" id = "custom.html">
Vikash Sharma
2

voici la solution faire un filtre comme celui-ci

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

et l'appliquer comme filtre au ng-bind-html comme

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

et merci à Ruben Decrop

bahri noredine
la source
1

Utilisation

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

et

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

Pour cela, vous devez inclure angular-sanitize.js, par exemple dans votre fichier html avec

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

Voici une bind-as-htmldirective simple (et peu sûre) , sans avoir besoin de ngSanitize:

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

Notez que cela s'ouvrira pour des problèmes de sécurité, si vous liez du contenu non approuvé.

Utilisez comme ça:

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

la source
-1

Exemple de travail avec pipe pour afficher du HTML dans le modèle avec Angular 4.

1. tuyau évalué 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. Enregistrez le tuyau sur app.module.ts

 import {EscapeHtmlPipe} from './components/pipes/escape-html.pipe';
    declarations: [...,EscapeHtmlPipe]
  1. Utiliser dans votre modèle

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

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

    Veuillez ajouter l'implémentation appropriée pour getDivHtml dans le fichier component.ts associé.

Sagar Misal
la source
1
Je pense qu'il travaille avec AngularJS, pas avec la version la plus récente.
Leprosy
-1

Utilisation simple [innerHTML], comme ci-dessous:

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

Avant de devoir utiliser ng-bind-html...

Alireza
la source
Ceci est uniquement disponible dans Angular (Angular version 2+), pas AngularJS (Angular version 1).
ste2425
-1

Dans Angular 7 + ionic 4, le contenu Html peut être affiché en utilisant "[innerHTML]":

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

J'espère que cela vous aidera également. Merci.

Kamlesh
la source
veuillez me dire ce qui ne va pas dans ce code, ce qui est la cause de downvote ce poste. J'ai testé ce code dans ma 2 application. Ça marche. Veuillez partager votre expérience. Merci beaucoup.
Kamlesh
1
AngularJS est égal à Angular 1.x. Angular 7 est un framework complètement différent
Aw Snap