filtro di nuova riga angularjs senza altro HTML


86

Sto cercando di convertire i caratteri di nuova riga ( \n) in html br.
Secondo questa discussione nel gruppo Google , ecco cosa ho:

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

La discussione consiglia inoltre di utilizzare quanto segue nella vista:

{{ dataFromModel | newline | html }}

Questo sembra usare il vecchio htmlfiltro, mentre ora dovremmo usare l' ng-bind-htmlattributo.


Indipendentemente da ciò, questo pone un problema: non voglio che alcun HTML dalla stringa originale ( dataFromModel) venga visualizzato come HTML; solo il br's.

Ad esempio, data la seguente stringa:

Anche se 7> 5
non voglio ancora HTML e roba qui ...

Vorrei che producesse:

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

C'è un modo per farlo?

Risposte:


279

Forse puoi farlo solo con html, un <preformated text>modo? Eviterà di utilizzare filtri o di eseguire qualsiasi tipo di elaborazione.

Tutto quello che devi fare è visualizzare il testo all'interno di un elemento che ha questo CSS:

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

Questo analizzerà e visualizzerà \ n come nuove righe. Funziona alla grande per me.

Qui, un esempio di jsFiddle .


79
pre-line, era un'opzione migliore per me.
Pepijn

7
+1, questa è di gran lunga la soluzione più semplice e sembra essere adatta a molte esigenze. In effetti, pre-lineè probabilmente migliore in generale, poiché le righe lunghe verranno avvolte (come farebbero con qualsiasi <br>soluzione basata).
tuomassalo

13
style = "white-space: pre-line;" è un'opzione migliore da usare all'interno di <div>, secondo me
Dmitri Algazin

7
pre-wrapsembra essere ciò che la maggior parte delle persone desidera (non pre-riga): "Lo spazio
vuoto

2
Ho scoperto che dovevo usare ng-bind = "MyMultiLineText" su <p> per impedire a Chrome di aggiungere righe extra davanti al mio testo
Scott Warren

33

Invece di scherzare con le nuove direttive, ho deciso di usare solo 2 filtri:

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;');
    }
});

Quindi, a mio avviso, ne convinco l'uno nell'altro:

<span ng-bind-html-unsafe="dataFromModel | noHTML | newlines"></span>

La tua regex per le nuove righe non funzionerà. Hai bisogno di: text.replace(/\\n/g, '<br />')o ancora megliotext.replace(/(\\r)?\\n/g, '<br />')
Bartłomiej Zalewski

2
@BarthZalewski - Hai solo bisogno di `\` quando compili una regex da una stringa. Quando usi una regex letterale non devi sfuggire alle barre.
MegaHit

2
Questo codice non funziona più poiché ng-bind-html-unsafe è deprecato.
Abhi

1
Ora puoi saltare il filtro noHtml se lo desideri e aggiungere semplicemente il filtro newLines a ng-bind-html. ngSanitize si prenderà cura del resto.
Dave Merwin

26

Un modo più semplice per farlo è creare un filtro che divida il testo in ciascuno di essi \nin un elenco, quindi utilizzare `ng-repeat.

Il filtro:

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

e nell'html:

<span ng-repeat="line in (text | newlines) track by $index">
    <p> {{line}}</p>
    <br>
</span>

4
Mi piace questa soluzione, ma andrebbe con un HTML più semplice:<p ng-repeat="line in (line.message | newlines)">{{line}}</p>
Thomas Fankhauser

2
Buona risposta, ma un migliore utilizzo track byin caso di linee duplicate, che genererà un errore: line in (text | newlines) track by $index.
JellicleCat

11

Se non vuoi distruggere il layout con stringhe infinite, usa la pre-riga:

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

6

Non so se Angular ha un servizio per rimuovere html, ma sembra che sia necessario rimuovere html prima di passare il newlinesfiltro personalizzato. Il modo in cui lo farei è attraverso una no-htmldirettiva personalizzata , a cui verrebbe passata una proprietà di ambito e il nome di un filtro da applicare dopo aver rimosso ilhtml

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

Ecco l'implementazione

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);
  };
});

La parte importante è il file text variabile. Qui creo un elemento DOM intermedio e gli accodo l'HTML usando il htmlmetodo e poi recupero solo il testo con il textmetodo. Entrambi i metodi sono forniti dalla versione lite di Angular di jQuery .

La parte seguente consiste nell'applicazione del newlinefiltro, che viene eseguita utilizzando il $filterservizio.

Controlla il plunker qui: http://plnkr.co/edit/SEtHH5eUgFEtC92Czq7T?p=preview


2

Un aggiornamento al filtro con ng-bind-html attualmente sarebbe:

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

e il filtro noHTML non è più necessario.

la soluzione per spazi bianchi sta avendo un basso supporto del browser: http://caniuse.com/#search=tab-size


0

Un po 'in ritardo per la festa su questo, ma suggerirei un piccolo miglioramento per verificare la presenza di stringhe non definite / nulle.

Qualcosa di simile a:

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

Oppure (un po 'più stretto)

.filter('newlines', function () {
    return function(text) {
        return (text instanceof String || typeof text === "string") ? text.replace(/(&#13;)?&#10;/g, '<br/>') : text;
    };
})
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.