фильтр новой строки angularjs без другого html


86

Я пытаюсь преобразовать символы новой строки ( \n) в HTML br.
Согласно этому обсуждению в группе Google , вот что у меня есть:

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

Обсуждение там также советует использовать в представлении следующее:

{{ dataFromModel | newline | html }}

Похоже, здесь используется старый htmlфильтр, тогда как теперь мы должны использовать ng-bind-htmlатрибут.


Тем не менее, это создает проблему: я не хочу, чтобы какой-либо HTML из исходной строки ( dataFromModel) отображался как HTML; только br's.

Например, учитывая следующую строку:

Хотя 7> 5,
я все еще не хочу, чтобы здесь были html и прочее ...

Я бы хотел, чтобы он выводил:

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

Есть ли способ добиться этого?

Ответы:


279

Может, можно добиться этого только с помощью html, <preformated text>способ? Это позволит избежать использования фильтров или какой-либо обработки.

Все, что вам нужно сделать, это отобразить текст внутри элемента с этим CSS:

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

Это проанализирует и отобразит \ n как новые строки. У меня отлично работает.

Вот пример jsFiddle .


79
pre-line, был для меня лучшим вариантом.
Pepijn

7
+1, это, безусловно, самое простое решение и, кажется, подходит для многих нужд. В самом деле, pre-lineвероятно, лучше в целом, поскольку длинные строки будут обернуты (как и в случае с любыми <br>другими решениями).
tuomassalo

13
style = "пробел: предварительная строка;" на мой взгляд, лучше использовать внутри <div>
Дмитрий Алгазин

7
pre-wrapпохоже, это то, чего хочет большинство людей (не перед строкой): «Пробелы сохраняются браузером. Текст будет переноситься при необходимости и при переносе
qwertzguy

2
Я обнаружил, что мне нужно использовать ng-bind = "MyMultiLineText" в <p>, чтобы Chrome не добавлял лишние строки перед моим текстом
Скотт Уоррен

33

Вместо того, чтобы возиться с новыми директивами, я решил использовать 2 фильтра:

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

Затем, на мой взгляд, я вставляю одно в другое:

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

Ваше регулярное выражение для новых строк не будет работать. Вам нужно: text.replace(/\\n/g, '<br />')или даже лучшеtext.replace(/(\\r)?\\n/g, '<br />')
Бартломей Залевски

2
@BarthZalewski - вам нужен только `\` при компиляции регулярного выражения из строки. При использовании литерала регулярного выражения вам не нужно избегать косой черты.
MegaHit

2
Этот код больше не работает, поскольку ng-bind-html-unsafe устарел.
Abhi

1
Теперь вы можете пропустить фильтр noHtml, если хотите, и просто добавить фильтр newLines в ng-bind-html. Об остальном позаботится ngSanitize.
Дэйв Мервин

26

Более простой способ сделать это - создать фильтр, который разбивает текст в каждом \nна список, а затем использовать `ng-repeat.

Фильтр:

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

и в html:

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

4
Мне нравится это решение, но я бы использовал более простой HTML:<p ng-repeat="line in (line.message | newlines)">{{line}}</p>
Томас Фанкхаузер,

2
Хороший ответ, но лучше использовать track byв случае дублирующих линий, которые бы вызвать ошибку: line in (text | newlines) track by $index.
JellicleCat

11

Если вы не хотите разрушать макет бесконечными строками, используйте pre-line:

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

6

Я не знаю, есть ли в Angular сервис для удаления html, но кажется, что вам нужно удалить html, прежде чем передавать свой newlinesсобственный фильтр. Я бы сделал это с помощью настраиваемой no-htmlдирективы, в которую было бы передано свойство области и имя фильтра, который будет применяться после удаленияhtml

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

Вот реализация

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

Важный бит - это textпеременная. Здесь я создаю промежуточный элемент DOM и добавляю к нему HTML с помощью htmlметода, а затем получаю только текст с помощью textметода. Оба метода предоставляются облегченной версией jQuery для Angular .

В следующей части применяется newlineфильтр, который выполняется с помощью $filterслужбы.

Проверьте плункер здесь: http://plnkr.co/edit/SEtHH5eUgFEtC92Czq7T?p=preview


2

Обновление фильтра с помощью ng-bind-html в настоящее время будет следующим:

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

и фильтр noHTML больше не требуется.

решение white-space имеет низкую поддержку браузера: http://caniuse.com/#search=tab-size


0

Немного поздно для вечеринки по этому поводу, но я бы предложил небольшое улучшение для проверки строк undefined / null.

Что-то типа:

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

Или (немного плотнее)

.filter('newlines', function () {
    return function(text) {
        return (text instanceof String || typeof text === "string") ? text.replace(/(&#13;)?&#10;/g, '<br/>') : text;
    };
})
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.