Angularjs newline filter 没有其他 html

我正在尝试将换行符(\n)转换为 html br的。
根据 谷歌小组的这个讨论,这是我得到的:

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

会上的讨论还建议采用以下观点:

{{ dataFromModel | newline | html }}

这似乎使用了旧的 html过滤器,而现在我们应该使用 ng-bind-html属性。


无论如何,这都会带来一个问题: 我不希望原始字符串(dataFromModel)中的任何 HTML 被呈现为 HTML; 只希望 br中的 HTML 呈现为 HTML。

例如,给定以下字符串:

而7 > 5
我还是不想在这里看到超文本标记语言和其他东西。

我想让它输出:

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

有办法完成吗?

79549 次浏览

I'm not aware if Angular has a service to strip html, but it seems you need to remove html before passing your newlines custom filter. The way I would do it is through a custom no-html directive, which would be passed a scope property and the name of a filter to apply after removing the html

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

Here's the implementation

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

The important bit is the text variable. Here I create an intermediate DOM element and append it the HTML using the html method and then retrieve only the text with the text method. Both methods are provided by Angular's lite version of jQuery.

The following part is applying the newline filter, which is done using the $filter service.

Check the plunker here: http://plnkr.co/edit/SEtHH5eUgFEtC92Czq7T?p=preview

Instead of messing with new directives, I decided to just use 2 filters:

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

Then, in my view, I pipe one into the other:

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

Maybe you can achieve this only with html, a <preformated text> way ? It will avoid from using filters or do any kind of processing.

All you have to do is display the text within an element that has this CSS:

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

This will parse and display \n as new lines. Works great for me.

Here, a jsFiddle example.

A simpler way to do this is to make a filter that splits the text at each \n into a list, and then to use `ng-repeat.

The filter:

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

and in the html:

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

An update to the filter with ng-bind-html currently would be:

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

and the noHTML filter is no longer required.

white-space solution is having low browser support: http://caniuse.com/#search=tab-size

Bit late to the party on this but I would suggest a small improvement to check for undefined / null strings.

Something like:

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

Or (bit tighter)

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

If you do not want to destroy the layout with endless strings, use pre-line:

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