Die Situation
In unserer Angular-App ist eine Direktive namens Page verschachtelt, die von einem Controller unterstützt wird und ein div mit dem Attribut ng-bind-html-unsafe enthält. Dies wird einer $ scope-Variable namens 'pageContent' zugewiesen. Dieser Variable wird dynamisch generiertes HTML aus einer Datenbank zugewiesen. Wenn der Benutzer zur nächsten Seite blättert, wird ein Aufruf an die Datenbank vorgenommen, und die Variable pageContent wird auf diesen neuen HTML-Code gesetzt, der über ng-bind-html-unsafe auf dem Bildschirm gerendert wird. Hier ist der Code:
Seitenrichtlinie
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
}
}
}
};
});
Vorlage der Seitenanweisung ("page.html" aus der Eigenschaft templateUrl oben)
<div ng-controller="PageCtrl" >
...
<!-- dynamic page content written into the div below -->
<div ng-bind-html-unsafe="pageContent" >
...
</div>
Seitencontroller
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;
});
});
Das funktioniert. Wir sehen den HTML-Code der Seite aus der Datenbank im Browser gut gerendert. Wenn der Benutzer zur nächsten Seite wechselt, wird der Inhalt der nächsten Seite usw. angezeigt. So weit, ist es gut.
Das Problem
Das Problem hierbei ist, dass wir interaktiven Inhalt innerhalb des Inhalts einer Seite haben möchten. Beispielsweise kann der HTML-Code ein Miniaturbild enthalten, in dem Angular, wenn der Benutzer darauf klickt, etwas Fantastisches tun sollte, z. B. das Anzeigen eines modalen Popup-Fensters. Ich habe Angular-Methodenaufrufe (ng-click) in die HTML-Zeichenfolgen in unserer Datenbank eingefügt, aber Angular erkennt natürlich weder Methodenaufrufe noch Direktiven, es sei denn, es analysiert die HTML-Zeichenfolge, erkennt sie und kompiliert sie.
In unserer DB
Inhalt für Seite 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>
Inhalt für Seite 2:
<p>Here's a snake. <img src="snake.png" ng-click="doSomethingAwesone('snake', 'playSound')" >Click to make him hiss.</p>
Zurück im Page-Controller fügen wir dann die entsprechende $ scope-Funktion hinzu:
Seitencontroller
$scope.doSomethingAwesome = function( id, action ) {
console.log( "Going to do " + action + " with "+ id );
}
Ich kann nicht herausfinden, wie diese 'doSomethingAwesome'-Methode aus der HTML-Zeichenfolge der Datenbank heraus aufgerufen werden kann. Mir ist klar, dass Angular die HTML-Zeichenfolge irgendwie analysieren muss, aber wie? Ich habe vage Gemurmel über den $ compile-Dienst gelesen und einige Beispiele kopiert und eingefügt, aber nichts funktioniert. Außerdem zeigen die meisten Beispiele, dass dynamischer Inhalt nur während der Verknüpfungsphase der Direktive festgelegt wird. Wir möchten, dass Page während des gesamten Lebens der App am Leben bleibt. Es empfängt, kompiliert und zeigt ständig neue Inhalte an, während der Benutzer durch die Seiten blättert.
In einem abstrakten Sinne könnte man sagen, dass wir versuchen, Angular-Blöcke dynamisch in einer Angular-App zu verschachteln und sie ein- und austauschen müssen.
Ich habe verschiedene Teile der Angular-Dokumentation mehrmals gelesen sowie alle Arten von Blog-Posts und JS hat mit dem Code der Leute herumgespielt. Ich weiß nicht, ob ich Angular völlig falsch verstehe oder nur etwas Einfaches vermisse oder ob ich langsam bin. Auf jeden Fall könnte ich einen Rat gebrauchen.
Antworten:
ng-bind-html-unsafe
rendert den Inhalt nur als HTML. Der Angular-Bereich wird nicht an das resultierende DOM gebunden. Zu$compile
diesem Zweck müssen Sie den Dienst nutzen. Ich habe diesen Plunker erstellt , um zu demonstrieren, wie$compile
eine Direktive erstellt wird, die von Benutzern eingegebenes dynamisches HTML rendert und an den Bereich des Controllers bindet. Die Quelle ist unten angegeben.demo.html
script.js
quelle
$compile(ele.contents())(scope);
- Diese Zeile löste mein Problem, keine Winkelkomponenten zu kompilieren, die dynamisch hinzugefügt werden. Vielen Dank.In Winkel 1.2.10 gab die Zeile
scope.$watch(attrs.dynamic, function(html) {
einen ungültigen Zeichenfehler zurück, da versucht wurde, den Wert vonattrs.dynamic
HTML-Text zu überwachen .Ich habe das behoben, indem ich das Attribut aus der Eigenschaft scope abgerufen habe
Mein Beispiel
quelle
$compile(ele.contents())(scope);
- Diese Zeile löste mein Problem, keine Winkelkomponenten zu kompilieren, die dynamisch hinzugefügt werden. Vielen Dank.Gefunden in einer Google-Diskussionsgruppe. Funktioniert bei mir.
quelle
Sie können verwenden
Direktive zum dynamischen Binden von HTML. Sie müssen die Daten jedoch über den Dienst $ sce abrufen.
Bitte sehen Sie die Live-Demo unter http://plnkr.co/edit/k4s3Bx
quelle
var myApp = angular.module('myApp', ['ngSanitize']);
Versuchen Sie diesen Code unten, um HTML über attr zu binden
Versuchen Sie diese element.html (scope.dynamic); als element.html (attr.dynamic);
quelle