it-swarm.com.de

Wie man ng-bind-html dazu bringt, eckigen Code zu kompilieren

Ich arbeite mit anglejs 1.2.0-rc.3. Ich möchte HTML-Code dynamisch in eine Vorlage einfügen. Dafür verwende ich im Controller:

html = "<div>hello</div>";
$scope.unicTabContent = $sce.trustAsHtml(html);

In der Vorlage habe ich:

<div id="unicTab" ng-bind-html="unicTabContent"></div>

Es funktioniert gut für normalen HTML-Code. Aber wenn ich versuche, angular Vorlage zu setzen, wird sie nicht interpretiert, sondern nur auf der Seite angezeigt. Zum Beispiel möchte ich Folgendes einfügen:

<div ng-controller="formCtrl">
    <div ng-repeat="item in content" ng-init="init()">
    </div>
</div>

Vielen Dank

52
Clement Roblot

Diese Lösung verwendet keine fest codierten Vorlagen und Sie können Angular Ausdrücke kompilieren, die in eine API-Antwort eingebettet sind.


Schritt 1. Installieren Sie diese Anweisung: https://github.com/incuna/angular-bind-html-compile

Schritt 2 Fügen Sie die Direktive in das Modul ein.

angular.module("app", ["angular-bind-html-compile"])

Schritt 3. Verwenden Sie die Direktive in der Vorlage:

<div bind-html-compile="letterTemplate.content"></div>

Ergebnis:

Controller-Objekt

 $scope.letter = { user: { name: "John"}}

JSON-Antwort

{ "letterTemplate":[
    { content: "<span>Dear {{letter.user.name}},</span>" }
]}

HTML-Ausgabe =

<div bind-html-compile="letterTemplate.content"> 
   <span>Dear John,</span>
</div>

Als Referenz ist hier die relevante Richtlinie:

(function () {
    'use strict';

    var module = angular.module('angular-bind-html-compile', []);

    module.directive('bindHtmlCompile', ['$compile', function ($compile) {
        return {
            restrict: 'A',
            link: function (scope, element, attrs) {
                scope.$watch(function () {
                    return scope.$eval(attrs.bindHtmlCompile);
                }, function (value) {
                    element.html(value);
                    $compile(element.contents())(scope);
                });
            }
        };
    }]);
}());
77
Ryan.lay

Dies ist, was ich gemacht habe, keine Ahnung, ob es der angular Weg istTM, aber es funktioniert und ist super einfach;

.directive('dynamic', function($compile) {
    return {
        restrict: 'A',
        replace: true,
        link: function (scope, element, attrs) {
            scope.$watch(attrs.dynamic, function(html) {
                $compile(element.html(html).contents())(scope);
            });
        }
    };
});

So;

<div id="unicTab" dynamic="unicTabContent"></div>

Edit: Ich fand den angular Weg , und es ist super einfach.

$templateCache.put('unicTabContent', $sce.trustAsHtml(html));
<div id="unicTab" ng-include="'unicTabContent'"></div>

Sie müssen keine eigenen Anweisungen oder Ähnliches erstellen. Aber es ist eine Art Einmal-Bindung, es werden keine Änderungen an Ihrem HTML-Code vorgenommen wie die benutzerdefinierte Direktive tut dies .

19
Hashbrown

Ich habe versucht, das Gleiche zu tun und bin auf dieses Modul gestoßen.

http://ngmodules.org/modules/ng-html-compile

Ich habe es einfach eingefügt und konnte dann "ng-html-compile" anstelle von "ng-bind-html" verwenden

2
nbarth

Wie Vinod Louis in seinem Kommentar sagt, war der beste Weg, dies zu tun, die Verwendung von Vorlagen. Ich musste eine Vorlage außerhalb des regulären Codes definieren, zum Beispiel habe ich diesen Code in meine index.html eingefügt:

<script type="text/ng-template" id="unic_tab_template.html">
    <div ng-switch on="page">
        <div ng-switch-when="home"><p>{{home}}</p></div>
        <div ng-switch-when="form">
            <div ng-controller="formCtrl">
                <div ng-repeat="item in content">{{item.name}}:{{item.value}}</div>
            </div>
        </div>
        <div ng-switch-default>an error accured</div>
    </div>
</script>

Diese Vorlage ist bedingt, sodass abhängig vom Wert von $ scope.page zwischen den drei Vorlagen umgeschaltet wird (die dritte ist eine Fehlerbehandlungsroutine). Um es zu benutzen, hatte ich:

<div id="unicTab" ng-controller="unicTabCtrl">
    <div ng-include="'unic_tab_template.html'"></div>
</div>

Auf diese Weise ändert sich meine Seite abhängig vom $ scope in meinem unicTabCtrl-Controller.

Die Idee, winklige Schablonennähte einzufügen, ist schwierig zu realisieren ($ compile seams ist die Lösung, aber ich konnte es nicht zum Laufen bringen). Stattdessen können Sie das bedingte Templating verwenden.

2
Clement Roblot

Meine Lösung für ein ähnliches Problem in meiner aktuellen App ohne Vorlage (nicht elegant, aber funktionierend):

directive('ngBindHtmlCompile', ['$compile', function ($compile) {
    return {
        restrict: 'A',
        compile: function compile(tElement, tAttributes, transcludeFn) {
            return function postLink(scope, element, attributes) {
                scope.$watch(function() {
                    return scope.$eval(attributes.ngBindHtml);
                }, function(newValue, oldValue) {
                    $compile(element.children())(scope);
                });
            };
        }
    };
}]);

Es erfordert ngBindHtml für dasselbe Element und kompiliert den Elementinhalt, nachdem er sich mit ngBindHtml geändert hat.

<div id="unicTab" ng-bind-html="unicTabContent" ng-bind-html-compile></div>

ng-html-compile sieht ähnlich aus, wird aber auf den ersten Blick nicht neu berechnet, wenn sich der Vorlageninhalt ändert. Aber ich habe es nicht ausprobiert.

1

Eine Möglichkeit ist die Verwendung einer Direktive, um benutzerdefinierte Vorlagen einzufügen, die angular Ausdrücke enthalten

<div id="unicTab" unic-tab-content></div>
app.directive("unicTabContent",function(){
   return {
      restrict:"A",
      template:'{{unicTabContent}}'
   }
})
1
charlietfl

Viel vereinfachte Lösung von @ clement-roblot basierend auf eingebauten Vorlagen.

Regler:

app.controller('TestCtrl', [
    '$scope',
    '$templateCache',
    function ($scope, $templateCache) {
        $templateCache.put('test.html', '2 + 2 = {{ 2 + 2 }}');
    }
]);

Aussicht:

<div ng-include="'test.html'"></div>
0
Stalinko

Der folgende Code ist mit den in Angular integrierten Objekten $ interpolate und $ sce viel einfacher. Fügen Sie zuerst die Objekte $ interpolate und $ sce Angular in Ihre Direktive ein, während Sie alles tun, was Sie in Ihrer Direktive brauchen.

amqApp.directive('myDir', ['$interpolate', '$sce', function ($interpolate,$sce ) {...}

Dann erstellen Sie alle Ihre Bereichsvariablen, die Sie in Ihren importierten HTML-Ausdrücken finden ...

$scope.custom = 'Hello World';

Als nächstes verwenden Sie $ interpolate, um Ihr benutzerdefiniertes HTML und seine Ausdrücke zu verarbeiten. Stellen Sie dann sicher, dass Sie das $ sce-Objekt verwenden, um es als HTML zu vertrauen, bevor Sie es binden.

var html = $interpolate('<b>{{custom}}</b>')($scope);    
$scope.data = $sce.trustAsHtml(html);

Stellen Sie schließlich in Ihrer Ansicht sicher, dass Sie ein Element mit dem Zusatz "ng-bind" oder "ng-bind-html" in Ihrer Ansichtsanzeige verwenden. Ich habe festgestellt, dass das $ sce-Teil den HTML-Code nicht als HTML-Code anzeigt (sieht ihn als Text an), wenn Sie ihn nicht wie folgt in Ihre HTML-Vorlage einbinden ...

<span ng-bind-html="data"></span>

Sie sollten in Fettdruck sehen ...

Hallo Welt

Ich habe diesen Trick verwendet, um Text/HTML mit benutzerdefinierten angular {{expressions}} aus einer web.config zu importieren.

0
Stokely