Inserir HTML na visualização do controlador AngularJS

800

É possível criar um fragmento HTML em um controlador AngularJS e ter esse HTML mostrado na exibição?

Isso vem de um requisito para transformar um blob JSON inconsistente em uma lista aninhada de id: valuepares. Portanto, o HTML é criado no controlador e agora estou procurando exibi-lo.

Eu criei uma propriedade de modelo, mas não posso renderizá-la na exibição sem apenas imprimir o HTML .


Atualizar

Parece que o problema surge da renderização angular do HTML criado como uma string entre aspas. Tentará encontrar uma maneira de contornar isso.

Controlador de exemplo:

var SomeController = function () {

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

Exemplo de visualização:

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

Dá:

<div>
    "<ul><li>render me please</li></ul>"
</div>
Swaff
fonte
1
Além disso, consulte esta pergunta , perguntando se é possível obter scripts no HTML inserido para execução.
04912 decig
É possível ter vários objetos vinculados ao mesmo ng-bind? como `` ng-bind = "site.address_1 site.address_2 site.zip"
fauverism 26/03
se você tiver muitas coisas em sua página, precisará alterar a linha 15046 de angular.js (insanidade) de function htmlSanitizer(html) {.... O desenvolvedor do Angular decidiu que você deve encontrar qualquer ligação em html, percorrendo lentamente todos os elementos ocultos de suas páginas, um por um, para encontrar aquele ÚNICO pedaço faltando de html. !!! muito zangado com essa suposição !!!
User3338098
Desculpe, a resposta escolhida por Lucas pode não ser a resposta totalmente correta. A resposta certa pode ser encontrada em outra pergunta aqui . Basicamente, "ng-bind-html-unsafe processa apenas o conteúdo como HTML. Não vincula o escopo Angular ao DOM resultante. Você precisa usar o serviço de compilação $ para esse fim".
gm2008
ng-bind remove todo o html interno. que não como filtro iria trabalhar é que é ok quando o filtro é o único valor
Muhammad Umer

Respostas:

1120

Para Angular 1.x, use ng-bind-htmlno HTML:

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

Nesse ponto, você receberá um attempting to use an unsafe value in a safe contexterro, portanto, você deve usar ngSanitize ou $ sce para resolver isso.

$ sce

Usar $sce.trustAsHtml() no controlador para converter a string html.

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

ngSanitize

Existem 2 etapas:

  1. inclua o recurso angular-sanitize.min.js, ou seja:
    <script src="lib/angular/angular-sanitize.min.js"></script>

  2. Em um arquivo js (controller ou geralmente app.js), inclua ngSanitize, ou seja:
    angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives', 'ngSanitize'])

Luke Madera
fonte
30
No Angular 1.2, ng-bind-html-unsafefoi removido e as duas diretivas foram combinadas. Veja: github.com/angular/angular.js/blob/master/…
Sasha Chedygov
60
Sem usar o ngSanitize, isso pode ser feito agora usando $sce. Injete-o no controlador e passe o html por ele. $scope.thisCanBeusedInsideNgBindHtml = $sce.trustAsHtml(someHtmlVar);Caso contrário, eu continuei recebendoattempting to use an unsafe value in a safe context
Matsemann
3
Precisamos de um pouco de limpeza aqui, que é o caminho certo que nada parece estar funcionando para mim.
desembarcou
9
stackoverflow.com/questions/21829275/... <- trabalhou para mim :) nenhuma das opções nas respostas aqui trabalhou infelizmente
anpatel
7
Para que as pessoas não fiquem desanimadas, a atualização mais recente desta resposta, juntamente com o requisito ngSanitize na parte inferior da resposta, funciona de fato.
Ben Cull1: 01:
312

Você também pode criar um filtro assim:

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

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

Então na vista

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

Nota : Este filtro confia em todo e qualquer html passado a ele e pode apresentar uma vulnerabilidade XSS se as variáveis ​​com entrada do usuário forem passadas para ele.

Katie Astrauskas
fonte
@ Katie Astrauskas, obrigado pela resposta! Maneira muito limpa. A ngResourcedependência de BTW não é necessária.
Athlan 7/03/15
28
Use isso somente quando confiar totalmente no HTML. Isso não limpa o HTML de nenhuma maneira, mas permite que o Angular o injete na página. HTML malicioso pode provocar ataques XSS.
precisa saber é o seguinte
Se o desempenho for importante, evite usar filtros. Um filtro acionará dois resumos de cada vez.
Tantelope
14
Por que o filtro é chamado sanitize? Isso é tão enganador quanto não desinfecta nada. Em vez disso, deve ser chamado trust, trustSafeou algo semelhante.
Denis Pshenov 9/10
1
Resposta maravilhosa. rawHtmlé o meu nome para o filtro em vez de sanitize.
Wumms
119

JS angular mostra HTML dentro da tag

A solução fornecida no link acima funcionou para mim, nenhuma das opções deste segmento funcionou. Para quem procura a mesma coisa com a versão 1.2.9 do AngularJS

Aqui está uma cópia:

Ok, eu encontrei solução para isso:

JS:

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

HTML:

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

EDITAR:

Aqui está a configuração:

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

    }]);

Arquivo HTML:

<div ng-controller="MyController">
    <div ng-bind-html="renderHtml(body)"></div>
</div>
anpatel
fonte
7
Esteja ciente de que você precisa ter absoluta certeza de que o html pode ser confiável. Caso contrário, a porta estará aberta para ataques XSS.
jan.vdbergh
Essa solução, usando uma função para renderizar o HTML, é a única que funcionou para mim.
MarceloBarbosa
para que serve o '$ http'?
Soldeplata Saketos
@SoldeplataSaketos nada em particular, acho que estava tentando localmente na época e acabei copiando a dependência.
Anpatel
A mesma resposta é atualizada aqui. stackoverflow.com/questions/21829275/…
Surya R Praveen
65

Felizmente, você não precisa de filtros sofisticados ou métodos não seguros para evitar essa mensagem de erro. Esta é a implementação completa para exibir corretamente a marcação HTML em uma exibição da maneira pretendida e segura.

O módulo de higienização deve ser incluído após o 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>

Em seguida, o módulo deve ser carregado:

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

Isso permitirá que você inclua a marcação em uma string de um controlador, diretiva, etc:

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

Finalmente, em um modelo, ele deve ser produzido da seguinte maneira:

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

O que produzirá a saída esperada: 42 é a resposta .

Pier-Luc Gendreau
fonte
1
Tente algum html como <div><label>Why My Input Element Missing</label><input /></div>... Se ele te surpreender, atualize sua resposta plz .. Porque eu testei todas as soluções de 10 + votos. Sua solução não funcionou para mim ver minhas tags de entrada .. bem, caso contrário .. eu usei$sce.trustAsHtml(html)
Sami
Esta solução funciona, gostaria de postar um jsfiddle ou plunkr?
Pier-Luc Gendreau
Isso deve realmente ser a resposta se estiver usando mais recente angular
Sandeep
61

Eu tentei hoje, a única maneira que encontrei foi essa

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

Damax
fonte
6
Essa solução deve ser usada apenas se a fonte for confiável para evitar ataques de script entre sites.
Bertrand
3
A partir do Angular 1.0.2, isso funciona para mim, sem a necessidade de outros arquivos ou conexões.
enigment
1
Usando o Angular 1.0.8 e isso funcionou para mim. Porém, observe o aviso de Heed @ Bertrand, não deixe de confiar na fonte.
Jack Slingerland
12
Para referência futura, ng-bind-html-unsafe foi removido na versão 1.2. Agora você precisa do módulo ngSanitize e, para vincular o html não seguro, deve usar o método $ sce.trustAsHtml.
Lucas Lazaro
53

ng-bind-html-unsafe não funciona mais.

Esta é a maneira mais curta:

Crie um filtro:

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

E na sua opinião:

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

PS Este método não requer que você inclua o ngSanitizemódulo.

Bidhan Bhattarai
fonte
3
Esta é a melhor solução que eu já vi aqui para o Angular 1.2. A solução usada $scena resposta aceita não funcionou para mim e eu não queria incluir uma dependência adicional para algo tão trivial.
Daniel Bonnell
A solução de Bidhan Bhattarai funcionou para mim. Angular 1.6.1
mediaguru
25

em 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

no controlador

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

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

trabalha também com $scope.comment.msg = $sce.trustAsHtml(html);

Sotos
fonte
1
$sceé legal, mas um usuário não pode simplesmente adicionar um ponto de interrupção aqui e restaurar qualquer código malicioso para this.myCtrl.comment.msgusar um depurador?
precisa saber é o seguinte
BradGreens novamente, você seria capaz de fazer o mesmo com o ng-bind-html-inseguro também?
precisa saber é o seguinte
4
Se alguém quiser invadir seu próprio navegador, pode, quem se importa. Não afetará outros usuários. @BradGreens Essa é a questão?
Chris Stephens
@ChrisStephens você está correto. Acho que isso responde à minha pergunta, mas minha opinião é que esses recursos estão mais próximos da segurança percebida do que da segurança real. Talvez ele proteja contra algum tipo de ataque automatizado? Eu nunca entendi claramente por que fazer isso realmente ajuda o aplicativo. Meu aplicativo precisa adicionar um filtro a TODAS as instâncias de renderização de wysiwyg HTML, pois ele pode ter CSS embutido, que ng-bind-htmlretira.
BradGreens
1
Bem, esses recursos ajudam a reduzir erros de codificação seguros. Em particular, o problema com a marcação / injeção de código. Por padrão, todos os dados vinculados são codificados para exibição. Então, basicamente, se você deseja imprimir a marcação, isso obriga a pensar no que você está tentando fazer. Sem esses recursos, você pode fazer muito apenas com a segurança do servidor, mas, para separar as preocupações, o aplicativo cliente deve cobrar pelo tratamento correto dos dados para exibição.
Chris Stephens
9

Eu descobri que o uso do ng-sanitize não me permitia adicionar o ng-click no html.

Para resolver isso, adicionei uma diretiva. Como isso:

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 este é o HTML:

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

Boa sorte.

Matt
fonte
6

Fiz isso usando ngBindHtml seguindo documentos angulares (v1.4) ,

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

Certifique-se de incluir ngSanitize nas dependências do módulo. Então deve funcionar bem.

Henry Neo
fonte
4

Outra solução, muito semelhante à do blrbr, exceto pelo uso de um atributo com escopo, é:

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 depois

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

Observe que você pode substituir element.append()porelement.replaceWith()

abbaf33f
fonte
3

existe mais uma solução para esse problema usando a criação de novos atributos ou diretivas em angular.

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

você também pode usar ng-include .

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

você pode usar "ng-show" para mostrar ocultar os dados deste modelo.

Vikash Sharma
fonte
Você tem certeza de que isso é tudo o que você precisa fazer para usar o ng-include?
fauverism
sim .. eu tentei. e se você estiver usando o modelo, use-o da seguinte maneira - <tipo de script = "text / ng-template" id = "custom.html">
Vikash Sharma
2

aqui está a solução faça um filtro como este

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

e aplique isso como um filtro ao ng-bind-html, como

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

e obrigado a Ruben Decrop

bahri noredine
fonte
1

Usar

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

e

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

Para isso, é necessário incluir angular-sanitize.js, por exemplo, no seu arquivo html com

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

Aqui está uma bind-as-htmldiretiva simples (e insegura) , sem a necessidade de ngSanitize:

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

Observe que isso será aberto para problemas de segurança, se vincular conteúdo não confiável.

Use assim:

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

fonte
-1

Exemplo de trabalho com pipe para exibir html no modelo com Angular 4.

1.Caneta Criada 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. Registre o pipe no app.module.ts

 import {EscapeHtmlPipe} from './components/pipes/escape-html.pipe';
    declarations: [...,EscapeHtmlPipe]
  1. Use no seu modelo

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

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

    Adicione a implementação apropriada para getDivHtml no arquivo component.ts associado.

Sagar Misal
fonte
1
Eu acho que ele está trabalhando com o AngularJS, não a versão mais recente.
Leprosy
-1

Apenas uso simples [innerHTML], como abaixo:

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

Antes de você precisar usar ng-bind-html...

Alireza
fonte
Isso está disponível apenas no Angular (versão angular 2+), não no AngularJS (versão angular 1).
ste2425 29/01
-1

No Angular 7 + iônico 4, o conteúdo em HTML pode ser mostrado usando "[innerHTML]":

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

Espero que isso também ajude você. Obrigado.

Kamlesh
fonte
por favor, diga-me o que há de errado neste código, o que é motivo para reduzir a votação deste post. Eu testei esse código no meu 2 aplicativo. Funciona. Por favor, compartilhe sua experiência. Muito obrigado.
Kamlesh #
1
AngularJS é igual a Angular 1.x. O Angular 7 é uma estrutura completamente diferente #
Aw Snap