Como criar filtro angularjs com saída HTML

90

Depois de ler a etapa 9 do tutorial do AngularJS , criei meu próprio filtro AngularJS, que deve converter dados booleanos em html.

Aqui está o meu código de filtro:

angular.module('phonecatFilters', []).filter('iconify', function () { // My custom filter
    return function (input) {
        return input ? '<i class="icon-ok"></i>' : '<i class="icon-remove"></i>';
    }
});

Aqui está meu código HTML:

<dt>Infrared</dt>
  <dd>{{phone.connectivity.infrared | iconify }}"></dd>

O problema é que borwser exibe o valor retornado literalmente como:

<i class="icon-ok"></i>

não como ícones (ou html renderizados) que deveriam aparecer.

Aqui está um exemplo JSFiddle

Acho que ocorre alguma higienização durante esse processo.

É possível desligar essa sanitização para este filtro específico?

Também sei como exibir ícones não retornando a saída HTML do filtro, mas apenas 'ok' ou 'remover' o texto que posso substituir por:

<i class="icon-{{phone.connectivity.infrared | iconify}}"><i>

mas não é isso que eu quero.

Pavel Kostenko
fonte

Respostas:

112

Você deve usar a ng-bind-htmldiretiva (requer para importar o módulo sanitize e o arquivo js): https://docs.angularjs.org/api/ng/directive/ngBindHtml

<span ng-bind-html='phone.connectivity.infrared | iconify'></span>

Você também precisa importar o CSS ( Bootstrap eu acho) para poder ver o ícone quando ele funciona.

Eu forneci um exemplo prático .

Guillaume86
fonte
2
Bem, é a única maneira que conheço de gerar html bruto com angularJS e essa ligação só é permitida em atributos, então você não tem muita escolha, você pode escrever sua própria diretiva que aceita comentários ou ligações de elementos, pegue o código-fonte de bind- html para um ponto de partida: github.com/angular/angular.js/blob/master/src/ngSanitize/…
Guillaume86
2
Uma diretiva pode ser a melhor solução aqui <check-icon ng: model = 'phone.connectivity.infrared'> </check-icon>, mas não é realmente mais curta do que a sua solução;)
Guillaume86
7
Uma coisa a observar é que você precisa incluir o angular-sanitize.jsarquivo para que isso funcione. Se quiser fazer o mesmo sem incluir essa biblioteca extra, você pode usar a ng-bind-html-unsafediretiva.
nwinkler
4
angular 2.x cai ng-html-bind-unsafee exige que o conteúdo html seja explicitamente marcado como 'seguro' - consulte: docs.angularjs.org/api/ng.$sce#Example
hooblei
1
Deve haver um filtro padrão html_safe:{{myContent | myFilter | html_safe}}
Augustin Riedinger
17

a menos que eu esteja lendo errado, você está abordando da maneira errada

Acho que ng-class é a diretiva necessária para este trabalho e é mais seguro do que renderizar para o atributo de classe.

no seu caso basta adicionar a string do objeto com as strings id como a classe e o valor como a expressão avaliada

<i ng-class="{
'icon-ok':!phone.connectivity.infrared,
'icon-remove':phone.connectivity.infrared
}"></i>'

em uma nota lateral, você só deve usar diretivas (integradas e personalizadas) para manipular html / dom e se precisar de um renderizador de html mais complexo, você deve olhar para a diretiva.

Gerard
fonte
Boa solução. Ou um pouco mais simples: <i ng-class="phone.connectivity.infrared ? 'icon-ok' : 'icon-remove'"></i>
Grade Trekkor de
11

Experimente este filtro

filter('trust', ['$sce',function($sce) {
  return function(value, type) {
    return $sce.trustAs(type || 'html', value);
  }
}]);

requer angular-higienizar

var app = angular.module("myApp", ['ngSanitize']);

Gist Link

Vikrant Mahajan
fonte