web-dev-qa-db-fra.com

Avec ng-bind-html-unsafe supprimé, comment puis-je injecter du HTML?

J'essaie d'utiliser le fournisseur $sanitize et la directive ng-bind-htm-unsafe pour permettre à mon contrôleur d'injecter du HTML dans un DIV.

Cependant, je ne peux pas le faire fonctionner.

<div ng-bind-html-unsafe="{{preview_data.preview.embed.html}}"></div>

J'ai découvert que c'est parce qu'il a été retiré de AngularJS (merci).

Mais sans ng-bind-html-unsafe, j'obtiens cette erreur:

http://errors.angularjs.org/undefined/$sce/unsafe

264
metalaureate
  1. Vous devez vous assurer que sanitize.js est chargé. Par exemple, chargez-le depuis https://ajax.googleapis.com/ajax/libs/angularjs/ [LAST_VERSION] /angular-sanitize.min.js
  2. vous devez inclure le module ngSanitize sur votre app, par exemple: var app = angular.module('myApp', ['ngSanitize']);
  3. il vous suffit de lier avec ng-bind-html le contenu original html. Pas besoin de faire autre chose dans votre contrôleur. L'analyse et la conversion sont effectuées automatiquement par la directive ngBindHtml. (Lisez la section How does it work _ à ce sujet: $ sce ). Donc, dans votre cas, <div ng-bind-html="preview_data.preview.embed.html"></div> ferait le travail.
120
p.matsinopoulos

Au lieu de déclarer une fonction dans votre portée, comme suggéré par Alex, vous pouvez la convertir en un simple filtre:

angular.module('myApp')
    .filter('to_trusted', ['$sce', function($sce){
        return function(text) {
            return $sce.trustAsHtml(text);
        };
    }]);

Ensuite, vous pouvez l'utiliser comme ceci:

<div ng-bind-html="preview_data.preview.embed.html | to_trusted"></div>

Et voici un exemple de travail: http://jsfiddle.net/leeroy/6j4Lg/1/

346
Leeroy Brun

Vous avez indiqué que vous utilisiez Angular 1.2.0 ... comme l’a indiqué l’un des autres commentaires, ng-bind-html-unsafe est obsolète.

Au lieu de cela, vous voudrez faire quelque chose comme ceci:

<div ng-bind-html="preview_data.preview.embed.htmlSafe"></div>

Dans votre contrôleur, insérez le service $sce, et marquez le code HTML comme "approuvé":

myApp.controller('myCtrl', ['$scope', '$sce', function($scope, $sce) {
  // ...
  $scope.preview_data.preview.embed.htmlSafe = 
     $sce.trustAsHtml(preview_data.preview.embed.html);
}

Notez que vous voudrez utiliser 1.2.0-rc3 ou plus récent. (Ils ont corrigé n bug dans rc3 qui empêchait les "observateurs" de fonctionner correctement avec du code HTML de confiance.)

274
ijprest

Pour moi, la solution la plus simple et la plus flexible est:

<div ng-bind-html="to_trusted(preview_data.preview.embed.html)"></div>

Et ajoutez des fonctions à votre contrôleur:

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

N'oubliez pas d'ajouter $sce à l'initialisation de votre contrôleur.

111
Alex

La meilleure solution à cela à mon avis est la suivante:

  1. Créez un filtre personnalisé pouvant par exemple figurer dans un fichier common.module.js - utilisé dans votre application:

    var app = angular.module('common.module', []);
    
    // html filter (render text as html)
    app.filter('html', ['$sce', function ($sce) { 
        return function (text) {
            return $sce.trustAsHtml(text);
        };    
    }])
    
  2. Usage:

    <span ng-bind-html="yourDataValue | html"></span>
    

Maintenant - je ne vois pas pourquoi la directive ng-bind-html ne fait pas trustAsHtml dans le cadre de sa fonction - me semble un peu bête de ne pas le faire

Quoi qu'il en soit - c'est ce que je fais - dans 67% des cas, cela fonctionne à tout moment.

63
Paul

Vous pouvez créer votre propre liaison HTML non sécurisée simple. Bien sûr, si vous utilisez les entrées de l'utilisateur, cela pourrait présenter un risque pour la sécurité.

App.directive('simpleHtml', function() {
  return function(scope, element, attr) {
    scope.$watch(attr.simpleHtml, function (value) {
      element.html(scope.$eval(attr.simpleHtml));
    })
  };
})
7
Jason Goemaat

Vous n'avez pas besoin d'utiliser {{}} à l'intérieur de ng-bind-html-unsafe:

<div ng-bind-html-unsafe="preview_data.preview.embed.html"></div>

Voici un exemple: http://plnkr.co/edit/R7JmGIo4xcJoBc1v4iki?p=preview

L'opérateur {{}} est essentiellement un raccourci pour ng-bind. Par conséquent, ce que vous tentiez d'essayer équivaut à une liaison dans une liaison, ce qui ne fonctionne pas.

5
ksimons

L'échappement contextuel strict peut être entièrement désactivé, ce qui vous permet d'injecter du code HTML à l'aide de ng-html-bind. C'est une option peu sûre, mais utile lors des tests.

Exemple tiré de la documentation AngularJS sur $sce :

angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {
  // Completely disable SCE.  For demonstration purposes only!
  // Do not use in new projects.
  $sceProvider.enabled(false);
});

Joindre la section de configuration ci-dessus à votre application vous permettra d’injecter du code HTML dans ng-html-bind, mais comme le remarque la doc:

SCE vous offre de nombreux avantages en termes de sécurité pour une surcharge de code minime. Il sera beaucoup plus difficile de prendre une application désactivée SCE et de la sécuriser par vous-même ou de l'activer ultérieurement. Il peut être judicieux de désactiver SCE dans les cas où beaucoup de code existant a été écrit avant l'introduction de SCE et que vous les migrez module par module.

2
Sean Fahey

Vous pouvez utiliser un filtre comme celui-ci

angular.module('app').filter('trustAs', ['$sce', 
    function($sce) {
        return function (input, type) {
            if (typeof input === "string") {
                return $sce.trustAs(type || 'html', input);
            }
            console.log("trustAs filter. Error. input isn't a string");
            return "";
        };
    }
]);

usage

<div ng-bind-html="myData | trustAs"></div>

il peut être utilisé pour d'autres types de ressources, par exemple un lien source pour des iframes et d'autres types déclarés ici

2
BotanMan

J'ai eu un problème similaire. Je ne pouvais toujours pas obtenir le contenu de mes fichiers de démarques hébergés sur github.

Après avoir configuré une liste blanche (avec le domaine github ajouté) dans $ sceDelegateProvider dans app.js, cela a fonctionné comme un charme.

Description: utilisation d’une liste blanche au lieu d’une personnalisation fiable si vous chargez du contenu à partir d’URL différentes.

Docs: $ sceDelegateProvider et ngInclude (pour extraire, compiler et inclure un fragment HTML externe)

2
Lahmizzar