AngularJS Newline-Filter ohne andere HTML

86

Ich versuche, Zeilenumbrüche ( \n) in HTML umzuwandeln br.
Gemäß dieser Diskussion in der Google-Gruppe habe ich Folgendes:

myApp.filter('newlines', function () {
    return function(text) {
        return text.replace(/\n/g, '<br/>');
    }
});

In der dortigen Diskussion wird außerdem empfohlen, in der Ansicht Folgendes zu verwenden:

{{ dataFromModel | newline | html }}

Dies scheint den alten htmlFilter zu verwenden, während wir jetzt das ng-bind-htmlAttribut verwenden sollen.


Unabhängig davon stellt dies ein Problem dar: Ich möchte nicht, dass HTML aus der ursprünglichen Zeichenfolge ( dataFromModel) als HTML gerendert wird. nur die br's.

Beispiel: Geben Sie die folgende Zeichenfolge ein:

Während 7> 5
möchte ich immer noch kein HTML & Zeug hier ...

Ich möchte, dass es ausgegeben wird:

While 7 &gt; 5<br>I still don't want html &amp; stuff in here...

Gibt es eine Möglichkeit, dies zu erreichen?

MegaHit
quelle

Antworten:

278

Vielleicht können Sie dies nur mit HTML erreichen, ein <preformated text>Weg? Es wird vermieden, Filter zu verwenden oder irgendeine Art von Verarbeitung durchzuführen.

Sie müssen lediglich den Text in einem Element mit diesem CSS anzeigen:

<p style="white-space: pre;">{{ MyMultiLineText}}</p>

Dadurch werden \ n als neue Zeilen analysiert und angezeigt. Funktioniert super für mich.

Hier ein jsFiddle-Beispiel .

Devin Spikowski
quelle
79
Pre-Line, war eine bessere Option für mich.
Pepijn
7
+1, dies ist bei weitem die einfachste Lösung und scheint für viele Anforderungen geeignet zu sein. In der Tat pre-lineist es wahrscheinlich im Allgemeinen besser, da lange Zeilen umbrochen werden (wie bei allen <br>basierten Lösungen).
Tuomassalo
13
style = "Leerraum: Vorzeile;" ist meiner Meinung nach die bessere Option, um in <div> zu verwenden
Dmitri Algazin
7
pre-wrapscheint das zu sein, was die meisten Leute wollen (keine Vorzeile): "Leerzeichen werden vom Browser beibehalten. Text wird bei Bedarf umbrochen und in Zeilenumbrüchen" von w3schools
qwertzguy
2
Ich musste ng-bind = "MyMultiLineText" auf dem <p> verwenden, um zu verhindern, dass Chrome zusätzliche Zeilen vor meinem Text hinzufügt
Scott Warren,
33

Anstatt mit neuen Anweisungen herumzuspielen, habe ich mich entschieden, nur zwei Filter zu verwenden:

App.filter('newlines', function () {
    return function(text) {
        return text.replace(/\n/g, '<br/>');
    }
})
.filter('noHTML', function () {
    return function(text) {
        return text
                .replace(/&/g, '&amp;')
                .replace(/>/g, '&gt;')
                .replace(/</g, '&lt;');
    }
});

Dann leite ich aus meiner Sicht eins in das andere:

<span ng-bind-html-unsafe="dataFromModel | noHTML | newlines"></span>
MegaHit
quelle
Ihre Regex für neue Zeilen funktioniert nicht. Sie brauchen: text.replace(/\\n/g, '<br />')oder noch bessertext.replace(/(\\r)?\\n/g, '<br />')
Bartłomiej Zalewski
2
@BarthZalewski - Sie benötigen nur `\`, wenn Sie einen regulären Ausdruck aus einer Zeichenfolge kompilieren. Wenn Sie ein Regex-Literal verwenden, müssen Sie sich keinen Schrägstrichen entziehen.
MegaHit
2
Dieser Code funktioniert nicht mehr, da ng-bind-html-unsafe veraltet ist.
Abhi
1
Sie können jetzt den noHtml-Filter überspringen, wenn Sie möchten, und den newLines-Filter einfach zu ng-bind-html hinzufügen. ngSanitize kümmert sich um den Rest.
Dave Merwin
26

Eine einfachere Möglichkeit, dies zu tun, besteht darin, einen Filter zu erstellen, der den Text jeweils \nin eine Liste aufteilt, und dann `ng-repeat zu verwenden.

Der Filter:

App.filter('newlines', function() {
  return function(text) {
    return text.split(/\n/g);
  };
});

und im HTML:

<span ng-repeat="line in (text | newlines) track by $index">
    <p> {{line}}</p>
    <br>
</span>
JJW5432
quelle
4
Ich mag diese Lösung, würde aber mit einfacherem HTML gehen:<p ng-repeat="line in (line.message | newlines)">{{line}}</p>
Thomas Fankhauser
2
Gute Antwort, aber bessere Verwendung track bybei doppelten Zeilen, die einen Fehler auslösen würden : line in (text | newlines) track by $index.
JellicleCat
11

Wenn Sie das Layout nicht mit endlosen Zeichenfolgen zerstören möchten, verwenden Sie die Vorzeile:

<p style="white-space: pre-line;">{{ MyMultiLineText}}</p>
Sebastian Viereck
quelle
6

Ich weiß nicht, ob Angular einen Dienst zum Entfernen von HTML hat, aber es scheint, dass Sie HTML entfernen müssen, bevor Sie Ihren newlinesbenutzerdefinierten Filter übergeben. Die Art und Weise, wie ich es tun würde, ist durch eine benutzerdefinierte no-htmlDirektive, die eine scope-Eigenschaft und den Namen eines Filters übergeben würde, der nach dem Entfernen des angewendet werden sollhtml

<div no-html="data" post-filter="newlines"></div>

Hier ist die Implementierung

app.directive('noHtml', function($filter){
  return function(scope, element, attrs){
    var html = scope[attrs.noHtml];
    var text = angular.element("<div>").html(html).text();

    // post filter
    var filter = attrs.postFilter;
    var result = $filter(filter)(text);

    // apending html
    element.html(result);
  };
});

Das wichtige Bit ist die textVariable. Hier erstelle ich ein DOM-Zwischenelement und hänge es mit der htmlMethode an den HTML-Code an und rufe dann nur den Text mit der textMethode ab. Beide Methoden werden von Angulars Lite-Version von jQuery bereitgestellt .

Im folgenden Teil wird der newlineFilter angewendet, der mithilfe des $filterDienstes ausgeführt wird.

Überprüfen Sie den Plunker hier: http://plnkr.co/edit/SEtHH5eUgFEtC92Czq7T?p=preview

jaime
quelle
2

Ein Update des Filters mit ng-bind-html wäre derzeit:

myApp.filter('newlines', function () {
  return function(text) {
    return text.replace(/(&#13;)?&#10;/g, '<br/>');
  }
});

und der noHTML-Filter wird nicht mehr benötigt.

Die White-Space-Lösung bietet nur geringe Browserunterstützung: http://caniuse.com/#search=tab-size

Alex Mounir
quelle
0

Etwas spät zur Party, aber ich würde eine kleine Verbesserung vorschlagen, um nach undefinierten / Null-Strings zu suchen.

Etwas wie:

.filter('newlines', function () {
    return function(text) {
        return (text) ? text.replace(/(&#13;)?&#10;/g, '<br/>') : text;
    };
})

Oder (etwas enger)

.filter('newlines', function () {
    return function(text) {
        return (text instanceof String || typeof text === "string") ? text.replace(/(&#13;)?&#10;/g, '<br/>') : text;
    };
})
Ben Edge
quelle