La situation
Une directive appelée Page, soutenue par un contrôleur, contient une div avec un attribut ng-bind-html-unsafe. Ceci est assigné à une var $ scope appelée 'pageContent'. Cette variable obtient un code HTML généré dynamiquement à partir d'une base de données. Lorsque l'utilisateur passe à la page suivante, un appel à la base de données est effectué et la variable pageContent est définie sur ce nouveau HTML, qui est rendu à l'écran via ng-bind-html-unsafe. Voici le code:
Directive de page
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
}
}
}
};
});
Modèle de la directive de page ("page.html" de la propriété templateUrl ci-dessus)
<div ng-controller="PageCtrl" >
...
<!-- dynamic page content written into the div below -->
<div ng-bind-html-unsafe="pageContent" >
...
</div>
Contrôleur de page
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;
});
});
Ça marche. Nous voyons le HTML de la page à partir de la base de données bien rendu dans le navigateur. Lorsque l'utilisateur passe à la page suivante, nous voyons le contenu de la page suivante, et ainsi de suite. Jusqu'ici tout va bien.
Le problème
Le problème ici est que nous voulons avoir un contenu interactif à l'intérieur du contenu d'une page. Par exemple, le HTML peut contenir une image miniature où, lorsque l'utilisateur clique dessus, Angular doit faire quelque chose de génial, comme afficher une fenêtre modale contextuelle. J'ai placé des appels de méthode Angular (ng-click) dans les chaînes HTML de notre base de données, mais bien sûr, Angular ne reconnaîtra ni les appels de méthode ni les directives à moins qu'il n'analyse la chaîne HTML, ne les reconnaisse et ne les compile.
Dans notre DB
Contenu de la page 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>
Contenu de la page 2:
<p>Here's a snake. <img src="snake.png" ng-click="doSomethingAwesone('snake', 'playSound')" >Click to make him hiss.</p>
De retour dans le contrôleur de page, nous ajoutons ensuite la fonction $ scope correspondante:
Contrôleur de page
$scope.doSomethingAwesome = function( id, action ) {
console.log( "Going to do " + action + " with "+ id );
}
Je ne peux pas comprendre comment appeler cette méthode 'doSomethingAwesome' à partir de la chaîne HTML de la base de données. Je me rends compte qu'Angular doit analyser la chaîne HTML d'une manière ou d'une autre, mais comment? J'ai lu de vagues marmonnements sur le service $ compile, et copié et collé quelques exemples, mais rien ne fonctionne. De plus, la plupart des exemples montrent que le contenu dynamique n'est défini que pendant la phase de liaison de la directive. Nous voudrions que Page reste en vie tout au long de la vie de l'application. Il reçoit, compile et affiche en permanence du nouveau contenu lorsque l'utilisateur parcourt les pages.
Dans un sens abstrait, je suppose que vous pourriez dire que nous essayons d'imbriquer dynamiquement des morceaux d'Angular dans une application Angular et que nous devons être en mesure de les échanger entre eux.
J'ai lu plusieurs fois plusieurs morceaux de documentation Angular, ainsi que toutes sortes de billets de blog et JS Fiddled with people code. Je ne sais pas si je ne comprends pas complètement Angular, ou si je manque simplement quelque chose de simple, ou peut-être que je suis lent. Dans tous les cas, je pourrais utiliser quelques conseils.
Réponses:
ng-bind-html-unsafe
rend uniquement le contenu au format HTML. Il ne lie pas la portée angulaire au DOM résultant. Vous devez utiliser le$compile
service à cette fin. J'ai créé ce plunker pour montrer comment l'utiliser$compile
pour créer une directive rendant le HTML dynamique entré par les utilisateurs et lié à la portée du contrôleur. La source est publiée ci-dessous.demo.html
script.js
la source
$compile(ele.contents())(scope);
- cette ligne a résolu mon problème de ne pas compiler les composants angulaires qui sont ajoutés dynamiquement. Merci.Dans angular 1.2.10, la ligne
scope.$watch(attrs.dynamic, function(html) {
renvoyait une erreur de caractère non valide car elle essayait de regarder la valeur deattrs.dynamic
qui était du texte html.J'ai corrigé cela en récupérant l'attribut de la propriété scope
Mon exemple
la source
$compile(ele.contents())(scope);
- cette ligne a résolu mon problème de ne pas compiler les composants angulaires qui sont ajoutés dynamiquement. Merci.Trouvé dans un groupe de discussion Google. Travaille pour moi.
la source
Vous pouvez utiliser
directive pour lier le HTML dynamiquement. Cependant, vous devez obtenir les données via le service $ sce.
Veuillez voir la démo en direct sur http://plnkr.co/edit/k4s3Bx
la source
var myApp = angular.module('myApp', ['ngSanitize']);
Essayez ce code ci-dessous pour lier html via attr
Essayez cet élément.html (scope.dynamic); que element.html (attr.dynamic);
la source