webentwicklung-frage-antwort-db.com.de

Escape-Zeichen &> in ng-bind in AngularJs

Ich habe einen Anwendungsfall, bei dem wir Zeichen "&" und ">" in einer Zeichenfolge enthalten können. z.B. Johnson & Johnson, value > 3. Während also die Antwort vom Server verschlüsselt wird, wird der Wert zum Wert & amp; 3'.

ng-bind unterstützt Folgendes nicht:

value > 3 wird für ngBind gerendert, während der Browser denselben Inhalt wie value > 3 darstellt.

http://jsfiddle.net/HKahG/2/

Ng:bind <div ng-bind="model"></div> 
Ng:bind-html <div ng-bind-html="model"></div>
<div> From Div: value &gt; </div>

Warum ist dieses standardmäßige Browserverhalten in ng-bind nicht vorhanden? Ich möchte nicht ng-bind-html verwenden (hat Probleme mit dem Wert < und ist kein HTML-Code) oder ng-bind-unsafe-html.

Meine Anwendung verfügt über dynamische Schlüsselwertfelder, die in verschiedenen Teilen der Anwendung angezeigt werden. Es ist daher zusätzlicher Aufwand erforderlich, wenn Sie eine separate Direktive oder einen Dekorator verwenden, um alle String-Felder anzuzeigen, als ngBind.

Fragen:

1) Gibt es eine andere Möglichkeit, dies ohne Verwendung einer zusätzlichen Direktive zu tun, oder ist dies die richtige Art, mit verschlüsselten Daten zu arbeiten?

2) Kann ich das Verhalten von ng-bind überschreiben oder standardmäßig dekorieren?

17
DarkKnight

EDIT: Bitte gehen Sie direkt zum Ende der Antwort, um die beste Version zu erhalten. Die Antwort ist in chronologischer Reihenfolge. Nach einigen Iterationen bekam ich am Ende den optimalen Code. Vielen Dank.

  • Kann ich das Verhalten von ng-bind standardmäßig außer Kraft setzen oder dekorieren?

Ja. Ich habe eine sehr einfache Implementierung vorgenommen, die ng-bind dazu bringt, sich so zu verhalten, wie Sie möchten. Ich bin mir nicht sicher, ob das genau das ist, was du willst, aber zumindest tut es, was ich verstanden habe.

Geige arbeiten: http://jsfiddle.net/93QQM/

Und hier ist der Code:

module.directive('ngBind', function() {
    return {
        compile: function(tElement, tAttrs) {
            tAttrs.ngBind = 'myBind(' + tAttrs.ngBind + ')';
            return { 
                pre: function(scope) {
                    scope.myBind = function(text) {
                        return angular.element('<div>' + text + '</div>').text();
                    }
                }
            };
        }
    }
});

Dies ist nicht gerade eine "zusätzliche Direktive" - ​​dies ist der Weg, um "das Verhalten von ng-bind zu überschreiben". Es fügt keine neue Direktive hinzu, sondern erweitert lediglich das Verhalten der vorhandenen ngBind-Direktive.

Bei der Funktion compile ändern wir den Wert des ng-bind-Attributs und wickeln ihn in einen Funktionsaufruf ein. Damit haben wir Zugriff auf den ursprünglichen Modellwert und die Möglichkeit, ihn modifiziert zurückzugeben.

Wir machen die Funktion durch den Gültigkeitsbereich in der Vorverknüpfungsphase verfügbar, da in der Nachverknüpfungsphase die Funktion nur after verfügbar ist, und die ursprüngliche ngBind-Direktive den Wert aus der Datenbank abgerufen hat Attribut (wird eine leere Zeichenfolge sein, da die Funktion nicht gefunden wird).

Die myBind-Funktion ist einfach und intelligent: Sie erstellt ein Element, und der Text wird unverändert als Elementkörper verwendet, der sofort über die text-Funktion abgerufen werden kann. Der Inhalt wird so zurückgegeben, wie er vom Browser gerendert wird.

Auf diese Weise können Sie ngBind wie üblich verwenden, wie <div ng-bind="model.content" />, aber dieses modifizierte Verhalten.


Verbesserte Version

Anstatt die myBind-Funktion an jeden Geltungsbereich anzufügen, in dem ngBind angewendet wird, können wir sie in jeder Vorverknüpfungsphase nur einmal an $rootScope anhängen, sodass sie sofort für alle Bereiche verfügbar ist.

Neue Arbeitsgeige: http://jsfiddle.net/EUqP9/

Neuer Code:

module.directive('ngBind', ['$rootScope', function($rootScope) {
    $rootScope.myBind = function(text) {
        return angular.element('<div>' + text + '</div>').text();
    };
    return {
        compile: function(tElement, tAttrs) {
            tAttrs.ngBind = 'myBind(' + tAttrs.ngBind + ')';
        }
    };
}]);

Viel sauberer als die vorherige Version! Natürlich können Sie den myBind-Funktionsnamen in einen beliebigen anderen Namen ändern. Die "Kosten" des Features sind folgende: Lassen Sie diese einfache Funktion zum Root-Bereich hinzufügen - Sie entscheiden selbst, ob sie den Preis wert ist.


Noch eine andere Version

Beeinflusst durch die Antwort von Chemiv ... warum nicht die Funktion aus irgendeinem Bereich entfernen und stattdessen einen Filter machen? Es funktioniert auch.

Noch eine weitere neue Geige: http://jsfiddle.net/hQJaZ/

Und der neue Code:

module.filter('decode', function() {
    return function(text) {
        return angular.element('<div>' + text + '</div>').text();
    };
}).directive('ngBind', function() {
    return {
        compile: function(tElement, tAttrs) {
            tAttrs.ngBind += '|decode';
        }
    };
});

Jetzt haben Sie drei Optionen zur Auswahl.

13
J. Bruni

Dieses ist HTML:

&gt;

Es hat zwar keine HTML-Tags, aber es ist immer noch HTML. Wenn Sie ng-bind verwenden möchten, muss Ihr Server nicht kodierten Text zurückgeben. Dh > anstelle von &gt;.

Verwenden Sie ng-bind-html, oder ändern Sie Ihren Server, um Klartext zurückzugeben, ohne dass HTML-Code zuerst kodiert wird.

Edit: Kurze Demo, die die Verwendung von &gt; und > in JavaScript veranschaulicht:

div1.innerHTML = "&gt;";  // write HTML
div2.textContent = ">";   // write plain text
console.log(div1.innerHTML === div2.innerHTML);
console.log(div1.textContent === div2.textContent);

http://jsfiddle.net/XhEcV/

12
gilly3

ng-bind verwendet die .text () -Methode, um Text zu ersetzen. Ihr Code enthält zwar &gt; (HTML-Markup), wird jedoch von ng-bind nicht korrekt wiedergegeben. Sie sollten ng-bind-html an dieser Stelle verwenden, da Sie tatsächlich HTML-Inhalt eingeben. Ansonsten können Sie> durch Regex zu '>' ersetzen.

zB: - model = model.replace(/&gt;/g, '>');

In diesem Fall müssen Sie jedoch alle HTML-Markierungen ersetzen, die nicht erforderlich sind, da ng-bind-html in Ihrem Fall bereits einwandfrei funktioniert.

6
Shreyance Jain

Ja, lass es uns mit einem Filter "dekorieren":

.filter("decode",function(){
    return function(str){         
      var el = document.createElement("div");
      el.innerHTML = str;
      str =   el.textContent || el.innerText;
      return str;        
    }
});

Und benutze es wie folgt: <div ng-bind="model|decode"></div>

Arbeitsbeispiel: http://jsfiddle.net/HKahG/5/

Inspiriert von dieser Antwort: https://stackoverflow.com/a/784698/1206613

5
Cherniv

Ich erinnere mich an eine Direktive namens ngBindHtmlUnsafe, die für solche Anwendungsfälle verfügbar ist.

http://code.angularjs.org/1.0.8/docs/api/ng.directive:ngBindHtmlUnsafe

Bitte beachten Sie dies. Nicht sicher, ob dies in späteren Unstable-Versionen verfügbar ist .. _ Dies ist ein Link zur neuesten verfügbaren stabilen Version.

1
Arshabh Agarwal

Warum nicht einfach $ sce.trustAsHtml verwenden?

0
Bob Barker