Cómo crear un filtro angularjs que genera HTML

90

Después de leer el paso 9 del tutorial de AngularJS , he creado mi propio filtro AngularJS, que debería convertir datos booleanos en html.

Aquí está mi 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>';
    }
});

Aquí está mi código HTML:

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

El problema es que borwser muestra el valor devuelto literalmente como:

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

no como iconos (o html renderizado) que deberían aparecer.

Aquí está el ejemplo de JSFiddle

Creo que se produce algo de desinfección durante este proceso.

¿Es posible desactivar esta desinfección para este filtro específico?

También sé cómo mostrar iconos al no devolver la salida HTML del filtro, sino simplemente 'aceptar' o 'eliminar' el texto que luego puedo sustituir por:

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

pero esto no es lo que quiero.

Pavel Kostenko
fuente

Respuestas:

112

Debe usar la ng-bind-htmldirectiva (requiere importar el módulo de desinfección y el archivo js): https://docs.angularjs.org/api/ng/directive/ngBindHtml

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

También necesita importar el CSS ( Bootstrap , supongo) para poder ver el icono cuando funciona.

Proporcioné un ejemplo práctico .

Guillaume86
fuente
2
Bueno, es la única forma que conozco de generar html sin procesar con angularJS y este enlace solo está permitido en atributos, por lo que no tiene muchas opciones, puede escribir su propia directiva que acepte comentarios o enlaces de elementos, tome el código fuente de bind- html para un punto de partida: github.com/angular/angular.js/blob/master/src/ngSanitize/…
Guillaume86
2
Una directiva tal vez sea la mejor solución aquí <check-icon ng: model = 'phone.connectivity.infrared'> </check-icon> pero no es realmente más corta que su solución;)
Guillaume86
7
Una cosa a tener en cuenta es que debe incluir el angular-sanitize.jsarchivo para que esto funcione. Si desea hacer lo mismo sin incluir esta biblioteca adicional, puede usar la ng-bind-html-unsafedirectiva.
nwinkler
4
angular 2.xy ng-html-bind-unsaferequiere que el contenido html se marque explícitamente como 'seguro'; consulte: docs.angularjs.org/api/ng.$sce#Example
hooblei
1
Debe haber un filtro predeterminado html_safe:{{myContent | myFilter | html_safe}}
Augustin Riedinger
17

a menos que lo esté leyendo mal, te estás acercando por el camino equivocado

Creo que ng-class es la directiva que necesita para este trabajo y es más segura que la representación en el atributo de clase.

en su caso, simplemente agregue la cadena de objeto con las cadenas de identificación como la clase y el valor como la expresión evaluada

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

en una nota al margen, solo debe usar directivas (integradas y personalizadas) para manipular html / dom y si necesita un render html más complejo, debe mirar la directiva en su lugar

Gerard
fuente
Buena solución. O hecho un poco más simple: <i ng-class="phone.connectivity.infrared ? 'icon-ok' : 'icon-remove'"></i>
Grid Trekkor
11

Prueba este filtro

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

requiere desinfección angular

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

Enlace Gist

Vikrant Mahajan
fuente