13

What is the best way to catch and format the "\n\n" inside of text being passed from the server to display line breaks? Fiddle is here: http://jsfiddle.net/nicktest2222/2vYBn/

$scope.data = [{
    terms: 'You agree to be bound be the terms of this site. \n\n Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus tempus lectus ac nunc malesuada, fringilla feugiat nibh rhoncus. Vestibulum adipiscing mi in est consectetur, vitae facilisis nulla tristique. Nam eu ante egestas, ultricies tellus eu, suscipit neque.\n\n Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum et ligula non tellus semper iaculis eget vestibulum metus. Nunc aliquam eros sit amet sapien posuere, ac hendrerit risus ultricies. Vivamus nec enim sed eros placerat pulvinar a quis dui.',
    agreed: false
}];
Nick
  • 592
  • 6
  • 12
  • 21

6 Answers6

17

You can also use a custom filter to replace \n to <br>.

<p ng-bind-html-unsafe="data[0].terms | nl2br"></p>

And the filter.

angular.module('myApp', [])
  .filter('nl2br', function(){
      return function(text) {
           return text ? text.replace(/\n/g, '<br>') : '';
      };
});

** EDIT/UPDATE - 2014-12-10 **

Since new versions of Angular removed ng-bind-html-unsafe @Tamlyn answer is now the best answer. I just changed the way $sce got injected into the function for speed purpose.

HTML

<p ng-bind-html="data[0].terms | nl2br"></p>

JS

.filter('nl2br', ['$sce', function ($sce) {
    return function (text) {
        return text ? $sce.trustAsHtml(text.replace(/\n/g, '<br/>')) : '';
    };
}]);

jsFiddle

L105
  • 5,379
  • 3
  • 18
  • 23
  • Beware, that using the version of the filter with $sce.trustAsHtml you enable XSS attacks on your page, if the attacker can modify the text (which he probably can). – Anton N Feb 11 '15 at 11:41
  • This is not a good solution for adding ````
    ```` tags to user generated text, as it renders any html the user inputs.
    – Adam Sep 17 '15 at 10:43
12

Angular 1.2 removed ng-bind-html-unsafe so here's an updated solution.

The HTML:

<p ng-bind-html="data[0].terms | nl2br"></p>

And the JS:

.filter('nl2br', function ($sce) {
    return function (text) {
        return text ? $sce.trustAsHtml(text.replace(/\n/g, '<br/>')) : '';
    };
})
Tamlyn
  • 22,122
  • 12
  • 111
  • 127
  • 1
    Beware, that using this filter you enable XSS attacks on your page, if the attacker can modify the text (which he probably can). – Anton N Feb 11 '15 at 11:40
6

You can use ngBindHtmlUnsafe directive, with terms: '... <br/><br/>...'

<p ng-bind-html-unsafe='data[0].terms'></p>

You can either send the html to the AngularJS, or send the string with \n and replace it with <br/> in AngularJS's controller. Either way should work. Hope it helps.

Demo

zs2020
  • 53,766
  • 29
  • 154
  • 219
6

You have the following options:

  • use pre tag and keep \n
  • use white-space:pre css rule and keep \n
  • replace \n with <br> tag as @sza offered.
vittore
  • 17,449
  • 6
  • 44
  • 82
  • `white-space: pre-line` will keep line breaks only, while the `white-space: pre` will keep other whitespaces too (e.g. indents with spaces). – fracz Apr 19 '16 at 07:17
2

If 'text' is null it returns an error, I added:

.filter('nl2br', function(){
    return function(text){
        return text?text.replace(/\n/g, '<br/>'):'';
    };
});
Jean F.
  • 1,775
  • 1
  • 19
  • 16
0

You can create a simple filter that will split your string into paragraphs:

.filter('lines', function() {
    return function(text) {
      return angular.isString(text) ? text.split(/\n/g) : text;
    }
  })   

And use it in view to display them:

<p ng-repeat="paragraph in myText | lines track by $index">{{ paragraph }}</p>

There is no need for bind-html-unsafe.

See this in action in the snippet:

angular.module('module', [])
  .filter('lines', function() {
    return function(text) {
      return angular.isString(text) ? text.split(/\n/g) : text;
    }
  })
  .controller('MyCtrl', function($scope) {
    $scope.myText = "First line\nSecondLine\nThird line\n\n\n\n\nAlone line";
  });
p {
  min-height: 1px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="module">
  <div ng-controller="MyCtrl">
    <p ng-repeat="paragraph in myText | lines track by $index">{{ paragraph }}</p>
  </div>
</div>

This is not my idea but I can't find the source right now

fracz
  • 20,536
  • 18
  • 103
  • 149