Filtre de nouvelle ligne angularjs sans autre html

86

J'essaye de convertir les caractères de nouvelle ligne ( \n) en html br.
Selon cette discussion dans le groupe Google , voici ce que j'ai:

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

La discussion conseille également d'utiliser les éléments suivants dans la vue:

{{ dataFromModel | newline | html }}

Cela semble utiliser l'ancien html filtre, alors que maintenant nous sommes censés utiliser l' ng-bind-htmlattribut.


Quoi qu'il en soit, cela pose un problème: je ne veux pas que le HTML de la chaîne d'origine ( dataFromModel) soit rendu au format HTML; seulement le br's.

Par exemple, étant donné la chaîne suivante:

Bien que 7> 5,
je ne veux toujours pas de html et d'autres choses ici ...

Je voudrais qu'il affiche:

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

Y a-t-il un moyen d'accomplir cela?

MegaHit
la source

Réponses:

279

Peut-être que vous ne pouvez y parvenir qu'avec html, d'une <preformated text>manière? Cela évitera d'utiliser des filtres ou d'effectuer tout type de traitement.

Tout ce que vous avez à faire est d'afficher le texte dans un élément qui a ce CSS:

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

Cela analysera et affichera \ n sous forme de nouvelles lignes. Fonctionne très bien pour moi.

Ici, un exemple jsFiddle .

Devin Spikowski
la source
79
pré-ligne, était une meilleure option pour moi.
Pepijn
7
+1, c'est de loin la solution la plus simple et semble convenir à de nombreux besoins. En effet, pre-linec'est probablement mieux en général, car les longues lignes seront encapsulées (comme elles le feraient avec toutes les <br>solutions basées).
tuomassalo
13
style = "espace blanc: pré-ligne;" est une meilleure option à utiliser à l'intérieur de <div>, à mon avis
Dmitri Algazin
7
pre-wrapsemble être ce que la plupart des gens veulent (pas en pré-ligne): "Les espaces blancs sont préservés par le navigateur. Le texte sera enveloppé si nécessaire, et les sauts de ligne" de w3schools
qwertzguy
2
J'ai trouvé que je devais utiliser ng-bind = "MyMultiLineText" sur <p> pour empêcher Chrome d'ajouter des lignes supplémentaires devant mon texte
Scott Warren
33

Au lieu de jouer avec de nouvelles directives, j'ai décidé d'utiliser simplement 2 filtres:

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

Ensuite, à mon avis, je passe l'un dans l'autre:

<span ng-bind-html-unsafe="dataFromModel | noHTML | newlines"></span>
MegaHit
la source
Votre regex pour les nouvelles lignes ne fonctionnera pas. Vous avez besoin de: text.replace(/\\n/g, '<br />')ou même mieuxtext.replace(/(\\r)?\\n/g, '<br />')
Bartłomiej Zalewski
2
@BarthZalewski - Vous n'avez besoin que de `\` lors de la compilation d'une regex à partir d'une chaîne. Lorsque vous utilisez un littéral regex, vous n'avez pas à échapper de barres obliques.
MegaHit
2
Ce code ne fonctionne plus car ng-bind-html-unsafe est obsolète.
Abhi
1
Vous pouvez maintenant ignorer le filtre noHtml si vous le souhaitez et ajouter simplement le filtre newLines à ng-bind-html. ngSanitize s'occupe du reste.
Dave Merwin
26

Une façon plus simple de faire cela est de créer un filtre qui divise le texte de chacun \ndans une liste, puis d'utiliser `ng-repeat.

Le filtre:

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

et dans le html:

<span ng-repeat="line in (text | newlines) track by $index">
    <p> {{line}}</p>
    <br>
</span>
JJW5432
la source
4
J'aime cette solution, mais j'irais avec un HTML plus simple:<p ng-repeat="line in (line.message | newlines)">{{line}}</p>
Thomas Fankhauser
2
Bonne réponse, mais une meilleure utilisation track byen cas de lignes en double, qui soulèveraient une erreur: line in (text | newlines) track by $index.
JellicleCat
11

Si vous ne voulez pas détruire la mise en page avec des chaînes sans fin, utilisez la pré-ligne:

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

Je ne sais pas si Angular a un service pour supprimer le html, mais il semble que vous deviez supprimer le html avant de passer votre newlinesfiltre personnalisé. La façon dont je le ferais consiste à utiliser une no-htmldirective personnalisée , à laquelle une propriété scope et le nom d'un filtre à appliquer après la suppression duhtml

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

Voici la mise en œuvre

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

Le bit important est la textvariable. Ici, je crée un élément DOM intermédiaire et je lui ajoute le HTML en utilisant la htmlméthode, puis je ne récupère que le texte avec la textméthode. Les deux méthodes sont fournies par la version lite d' Angular de jQuery .

La partie suivante applique le newlinefiltre, ce qui est fait à l'aide du $filterservice.

Vérifiez le plunker ici: http://plnkr.co/edit/SEtHH5eUgFEtC92Czq7T?p=preview

jaime
la source
2

Une mise à jour du filtre avec ng-bind-html serait actuellement:

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

et le filtre noHTML n'est plus nécessaire.

La solution d'espace blanc a une faible prise en charge du navigateur: http://caniuse.com/#search=tab-size

Alex Mounir
la source
0

Un peu tard à la fête à ce sujet, mais je suggérerais une petite amélioration pour vérifier les chaînes non définies / nulles.

Quelque chose comme:

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

Ou (un peu plus serré)

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