Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preserve line breaks in angularjs

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


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)


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

.angular-with-newlines {
  white-space: pre;
}
  • Look ma! No extra HTML tags!

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


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.


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.


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
}