La situación
Anidado dentro de nuestra aplicación Angular hay una directiva llamada Page, respaldada por un controlador, que contiene un div con un atributo ng-bind-html-inseguro. Esto se asigna a un $ scope var llamado 'pageContent'. A esta var se le asigna HTML generado dinámicamente desde una base de datos. Cuando el usuario pasa a la página siguiente, se realiza una llamada a la base de datos y la variable pageContent se establece en este nuevo HTML, que se muestra en pantalla a través de ng-bind-html-inseguro. Aquí está el código:
Directiva de la página
angular.module('myApp.directives')
.directive('myPage', function ($compile) {
return {
templateUrl: 'page.html',
restrict: 'E',
compile: function compile(element, attrs, transclude) {
// does nothing currently
return {
pre: function preLink(scope, element, attrs, controller) {
// does nothing currently
},
post: function postLink(scope, element, attrs, controller) {
// does nothing currently
}
}
}
};
});
Plantilla de directiva de página ("page.html" de la propiedad templateUrl anterior)
<div ng-controller="PageCtrl" >
...
<!-- dynamic page content written into the div below -->
<div ng-bind-html-unsafe="pageContent" >
...
</div>
Controlador de página
angular.module('myApp')
.controller('PageCtrl', function ($scope) {
$scope.pageContent = '';
$scope.$on( "receivedPageContent", function(event, args) {
console.log( 'new page content received after DB call' );
$scope.pageContent = args.htmlStrFromDB;
});
});
Eso funciona. Vemos el HTML de la página de la base de datos bien representada en el navegador. Cuando el usuario pasa a la página siguiente, vemos el contenido de la página siguiente, y así sucesivamente. Hasta aquí todo bien.
El problema
El problema aquí es que queremos tener contenido interactivo dentro del contenido de una página. Por ejemplo, el HTML puede contener una imagen en miniatura donde, cuando el usuario hace clic en él, Angular debería hacer algo increíble, como mostrar una ventana modal emergente. He colocado llamadas a métodos angulares (ng-click) en las cadenas HTML de nuestra base de datos, pero, por supuesto, Angular no reconocerá las llamadas a métodos ni las directivas a menos que de alguna manera analice la cadena HTML, las reconozca y las compile.
En nuestro DB
Contenido para la página 1:
<p>Here's a cool pic of a lion. <img src="lion.png" ng-click="doSomethingAwesone('lion', 'showImage')" > Click on him to see a large image.</p>
Contenido para la página 2:
<p>Here's a snake. <img src="snake.png" ng-click="doSomethingAwesone('snake', 'playSound')" >Click to make him hiss.</p>
De vuelta en el controlador de página, agregamos la función $ scope correspondiente:
Controlador de página
$scope.doSomethingAwesome = function( id, action ) {
console.log( "Going to do " + action + " with "+ id );
}
No puedo entender cómo llamar a ese método 'doSomethingAwesome' desde la cadena HTML de la base de datos. Me doy cuenta de que Angular tiene que analizar la cadena HTML de alguna manera, pero ¿cómo? Leí murmullos vagos sobre el servicio de compilación $, y copié y pegué algunos ejemplos, pero nada funciona. Además, la mayoría de los ejemplos muestran que el contenido dinámico solo se configura durante la fase de enlace de la directiva. Queremos que Page se mantenga con vida durante toda la vida de la aplicación. Constantemente recibe, compila y muestra contenido nuevo a medida que el usuario pasa las páginas.
En un sentido abstracto, supongo que se podría decir que estamos tratando de anidar dinámicamente trozos de Angular dentro de una aplicación Angular, y necesitamos poder intercambiarlos dentro y fuera.
He leído varias partes de la documentación angular varias veces, así como todo tipo de publicaciones de blog, y JS jugueteó con el código de las personas. No sé si estoy entendiendo completamente mal Angular, o simplemente me falta algo simple, o tal vez soy lento. En cualquier caso, podría usar algunos consejos.
Respuestas:
ng-bind-html-unsafe
solo representa el contenido como HTML. No une el alcance angular al DOM resultante. Tienes que usar el$compile
servicio para ese propósito. He creado este plunker para demostrar cómo utilizar$compile
para crear una representación HTML dinámico Directiva ponen los usuarios y la unión a alcance del controlador. La fuente se publica a continuación.demo.html
script.js
fuente
$compile(ele.contents())(scope);
- esta línea resolvió mi problema de no compilar componentes angulares que se agregan dinámicamente. Gracias.En angular 1.2.10, la línea
scope.$watch(attrs.dynamic, function(html) {
devolvía un error de carácter no válido porque intentaba ver el valor delattrs.dynamic
cual era texto html.Lo arreglé recuperando el atributo de la propiedad del alcance
Mi ejemplo
fuente
$compile(ele.contents())(scope);
- esta línea resolvió mi problema de no compilar componentes angulares que se agregan dinámicamente. Gracias.Encontrado en un grupo de discusión de google. Funciona para mi.
fuente
Puedes usar
directiva para enlazar html dinámicamente. Sin embargo, debe obtener los datos a través del servicio $ sce.
Vea la demostración en vivo en http://plnkr.co/edit/k4s3Bx
fuente
var myApp = angular.module('myApp', ['ngSanitize']);
Pruebe este código a continuación para vincular html a través de attr
Pruebe este element.html (scope.dynamic); que element.html (attr.dynamic);
fuente