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...

Чи є спосіб досягти цього?

Відповіді:


278

Можливо, ви можете досягти цього лише за допомогою html, a <preformated text> ? Це дозволить уникнути використання фільтрів або будь-якої обробки.

Все, що вам потрібно зробити, це відобразити текст в елементі, який має такий CSS:

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

Це буде проаналізовано та відображено \ n як нові рядки. Для мене чудово працює.

Ось приклад jsFiddle .


79
перед лінією, був кращим варіантом для мене.
Pepijn

7
+1, це на сьогоднішній день найпростіше рішення і, здається, підходить для багатьох потреб. Дійсно, pre-lineце, мабуть, краще взагалі, оскільки довгі рядки будуть обгорнуті (як це було б із будь-якими <br>заснованими рішеннями).
tuomassalo

13
style = "white-space: pre-line;" кращий варіант використовувати всередині <div>, на мій погляд
Дмитро Алгазін

7
pre-wrapздається, це те, що хоче більшість людей (не перед рядком): "Пробіл зберігається браузером. Текст обернеться, коли це буде потрібно, і розриви рядків" від w3schools
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 застарілий.
Абхі

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

Якщо ви не хочете знищувати макет нескінченними рядками, використовуйте попередній рядок:

<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

Трохи пізно на вечірку щодо цього, але я б запропонував невелике вдосконалення для перевірки на невизначені / нульові рядки.

Щось на зразок:

.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.