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.