187

I have seen this SO question.

My code instead of ng-bind="item.desc" uses {{item.desc}} because I have a ng-repeat before.

So my code:

<div ng-repeat="item in items">
  {{item.description}}
</div>

The item description contains \n for newlines which are not rendered.

How can the {{item.description}} display the newlines easily assuming that I have the ng-repeat above?

Community
  • 1
  • 1
Diolor
  • 13,181
  • 30
  • 111
  • 179
  • Put it in a
     tag?
    – aet Oct 30 '13 at 14:18
  • 93
    By styling the wrapper `div` with `style="white-space:pre-wrap;"`. – Stewie Oct 30 '13 at 15:21
  • 1
    @Stewie 's comment works perfectly for me (AngularJS 1.2.18), it explicitly shows how to style the individual element (as opposed to pilau's and Paul Weber's solution) and no need to change the styles of the
     tag as others proposed.
    – Andre Holzner Nov 28 '14 at 09:42
  • You are right, I assumed that everyone knows how to use basic css and apply a class to an element. If Stewie had posted his comment as an answer it would have been better for him. Though it seems as if he has enough points ... – Paul Weber Jan 05 '15 at 11:34
  • I agree, @Stewie definitely should have formatted his comment as an answer. It fixed my issue perfectly. – CF_HoneyBadger Jan 15 '15 at 20:44
  • @Stewie your the best :+1: that is exactly what should be done with \n but you'll have to be careful where you use it :-). – Sebastian Feb 04 '15 at 12:58
  • possible duplicate of [how can i preserve new lines in an angular partial](http://stackoverflow.com/questions/15449325/how-can-i-preserve-new-lines-in-an-angular-partial) – Matsemann Feb 25 '15 at 19:49
  • @Matsemann as you can see I start my question with the fact that I had see the possible duplicate and hadn't solved my answer :) – Diolor Feb 26 '15 at 03:01
  • Make sure you're not using a

    tag, this will limit the newline to 1max.

    – Peege151 May 22 '17 at 00:29

10 Answers10

307

Based on @pilau s answer - but with an improvement that even the accepted answer does not have.

<div class="angular-with-newlines" ng-repeat="item in items">
   {{item.description}}
</div>

/* in the css file or in a style block */
.angular-with-newlines {
    white-space: pre-line;
}

This will use newlines and whitespace as given, but also break content at the content boundaries. More information about the white-space property can be found here:

https://developer.mozilla.org/en-US/docs/Web/CSS/white-space

If you want to break on newlines, but also not collapse multiple spaces or white space preceeding the text (to render code or something), you can use:

white-space: pre-wrap;

Nice comparison of the different rendering modes: http://meyerweb.com/eric/css/tests/white-space.html

Paul Weber
  • 6,518
  • 3
  • 43
  • 52
  • 2
    Best solution here IMO, as it doesn't restyle to a mono-spaced font like pre. – Troels Larsen Oct 16 '14 at 13:05
  • 1
    Watch the white-space preceding the text, that will be preserved. – Silver Paladin Jan 09 '15 at 18:05
  • 2
    Since you brought it up wouldn't be `pre-line` the preferred one? It's closer to the way HTML usually renders the the text contents of its nodes and still preservers the newlines. – Knörpeltäng Jan 27 '15 at 18:19
  • Hmm... you are right, pre-line is the better solution, after I am not sure anymore why I choose pre-wrap instead of pre-line. Maybe the browser support for pre-line is not as good? But I will add this to the answer... Here is a comparison of the renderings: http://meyerweb.com/eric/css/tests/white-space.html – Paul Weber Jan 28 '15 at 11:35
  • 1
    This should be the accepted answer! `pre-line` is the way to go. Thanks Paul! – demisx Jan 30 '15 at 03:10
  • Don't forget the prefixes: white-space: -moz-pre-wrap; /* Firefox */ white-space: -o-pre-wrap; /* Opera mini */ white-space: pre-wrap; /* css-3 */ (http://caniuse.com/#search=pre-wrap) – StinkyCat Mar 27 '17 at 16:46
126

Try:

<div ng-repeat="item in items">
  <pre>{{item.description}}</pre>
</div>

The <pre> wrapper will print text with \n as text

also if you print the json, for better look use json filter, like:

<div ng-repeat="item in items">
  <pre>{{item.description|json}}</pre>
</div>

Demo

I agree with @Paul Weber that white-space: pre-wrap; is better approach, anyways using <pre> - the quick way mostly for debug some stuff (if you don't want to waste time on styling)

Maxim Shoustin
  • 77,483
  • 27
  • 203
  • 225
  • The item.description is text which has the `\n` in areas that I do not know, not at the end. I think I need the `pre` based on your edit. – Diolor Oct 30 '13 at 14:18
  • 30
    A lot of times, a
     tag isn't a good solution since it transforms the text into courier and breaks the style of the page. The style="white-space:pre-wrap;" solution seems to be a better solution (at least for my situation)
    – CF_HoneyBadger Jan 15 '15 at 20:42
  • 1
    @CF_HoneyBadger well, for you `@pilau`'s answer is proper one but it doesn't mean that mine is wrong and therefore i got downvoted – Maxim Shoustin Jan 15 '15 at 21:31
  • I tried converting all `\n`'s over to `
    `'s and then of course these tags weren't being rendered as HTML markup...after all this converting found your `style` solution and this is an incredible help and simplification...now I don't have to keep converting around all my backend data and just make a few changes in the View...You deserve +1000!
    – twknab Aug 31 '17 at 02:39
  • This works for code, but not for showing messages to users for example. I think Paul's answer is the correct one – Quintonn Jun 27 '18 at 09:13
63

It's so simple with CSS (it works, I swear).

.angular-with-newlines {
  white-space: pre;
}
  • Look ma! No extra HTML tags!
pilau
  • 6,635
  • 4
  • 56
  • 69
  • @pilau I wanna wrap the text if it contains comma(,) not white space how can I do this? – Shailendra Madda Sep 20 '14 at 11:38
  • @shylendra my solution doesn't wrap text, it makes it behave as if it were in a `pre` tag. Perhaps open another question? Or maybe I missed your point? – pilau Sep 21 '14 at 14:13
  • I was wondering about the browser compability. According to this chart, it seems to work in all major browsers. It is a lot less hassle than replacing newlines with br tags. Thanks! Just pay attention to format the code so it contains no spaces, they will show up of course. https://developer.mozilla.org/en-US/docs/Web/CSS/white-space – Paul Weber Oct 01 '14 at 12:57
  • Might be even better to use white-space: pre-wrap, else the content will never wrap. – Paul Weber Oct 01 '14 at 13:04
17

With CSS this can be achieve easily.

<div ng-repeat="item in items">
<span style="white-space:pre-wrap;"> {{item.description}}</span>
</div>  

Or a CSS class can be created for this purpose and can be used from external CSS file

Rehan
  • 197
  • 1
  • 7
2

Well it depends, if you want to bind datas, there shouldn't be any formatting in it, otherwise you can bind-html and do description.replace(/\\n/g, '<br>') not sure it's what you want though.

1

the css solution works, however you do not really get control on the styling. In my case I wanted a bit more space after the line break. Here is a directive I created to handle this (typescript):

function preDirective(): angular.IDirective {
    return {
        restrict: 'C',
        priority: 450,
        link: (scope, el, attr, ctrl) => {
            scope.$watch(
                () => el[0].innerHTML,
                (newVal) => {
                    let lineBreakIndex = newVal.indexOf('\n');
                    if (lineBreakIndex > -1 && lineBreakIndex !== newVal.length - 1 && newVal.substr(lineBreakIndex + 1, 4) != '</p>') {
                        let newHtml = `<p>${replaceAll(el[0].innerHTML, '\n\n', '\n').split('\n').join('</p><p>')}</p>`;
                        el[0].innerHTML = newHtml;
                    }
                }
            )
        }
    };

    function replaceAll(str, find, replace) {
        return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
    }

    function escapeRegExp(str) {
        return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
    }
}

angular.module('app').directive('pre', preDirective);

Use:

<div class="pre">{{item.description}}</div>

All it does is wraps each part of the text in to a <p> tag. After that you can style it however you want.

Dmitry Efimenko
  • 10,973
  • 7
  • 62
  • 79
1

Just add this to your styles, this works for me

white-space: pre-wrap

By this text in <textarea>can be display as it's in there with spaces and line brakes

HTML

   <p class="text-style">{{product?.description}}</p>

CSS

.text-style{
    white-space: pre-wrap
}
Akitha_MJ
  • 3,882
  • 25
  • 20
0

Yes, I would either use the <pre> tag or use ng-bind-html-unsafe http://docs-angularjs-org-dev.appspot.com/api/ng.directive:ngBindHtmlUnsafe (use ng-bind-html if you are using 1.2+) after using .replace() to change /n to <br />

NicolasMoise
  • 7,261
  • 10
  • 44
  • 65
0

Just use the css style "white-space: pre-wrap" and you should be good to go. I've had the same issue where I need to handle error messages for which the line breaks and white spaces are really particular. I just added this inline where I was binding the data and it works like Charm!

Sidd Thota
  • 2,040
  • 1
  • 20
  • 24
0

I had a similar problem to you. I'm not that keen on the other answers here because they don't really allow you to style the newline behaviour very easily. I'm not sure if you have control over the original data, but the solution I adopted was to switch "items" from being an array of strings to being an array of arrays, where each item in the second array contained a line of text. That way you can do something like:

<div ng-repeat="item in items">
  <p ng-repeat="para in item.description">
     {{para}}
  </p>
</div>

This way you can apply classes to the paragraphs and style them nicely with CSS.

Chris Rae
  • 5,627
  • 2
  • 36
  • 51