13

I am trying to get a string to be displayed on a webpage through Angularjs which may have multiple lines. Here is what I have got:

<textarea ng-model="StringValue"></textarea>
{{StringValue}}

When you type into the textarea:

"This is

a string"

you get:

"This is a string"

How do you get it so the text is displayed the same way it is typed?

8 Answers 8

20

Be careful with ng-bind-html - very easy to get XSS-injection.

If you want to show your newlines only, without XSS in your pages
you can use simple css-rule: white-space: pre:

<span style="white-space: pre">{{multilinetext}}</span>

Sure, you can make css-class for this:

<style>.pre {white-space: pre}</style>
<span class="pre">{{multilinetext}}</span>

Also, this method makes all whitespaces visible: leading spaces, multiple spaces tabs and so other.

Sign up to request clarification or add additional context in comments.

Comments

12

This is an issue with HTML. Not Angular. Angular is writing out exactly what you told it to.

In HTML, outside of a <pre> tag, endless whitespace (returns, tabs, spaces, etc) are all treated as one white space. This is why you need things like <br/> and &nbsp; if you're not using a <pre> tag block.

So try this in HTML just so you get an understanding of what's happening:

<h3>Plain DIV</h3>
<div>
Some
   text
      here
</div>

<h3>Now with non-breaking spaces and line breaks</h3>
<div>
Some<br/>
&nbsp;&nbsp;&nbsp;text<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;here<br/>
</div>

<h3>Now with a PRE tag</h3>
<pre>
Some
   text
      here
</pre>

Here's a Fiddle demonstrating the above.

You're going to need to style the PRE tag with some custom class to make it look like the other text on your page, though, because most default styles for <pre> are going to use mono-spaced (fixed-width) fonts like Courier or Consolas.

It's either that or you're going to have to write a filter in angular that processes spaces, tabs and line breaks into the proper markup. ... which will be a pain to maintain.

EDIT: with the understanding above, an Angular solution (if you don't just use PRE)

So the best solution, IMO, if you don't want to use the <pre> tag would be to create a filter that will scrub the text for you and farmat it with line breaks and non-breaking spaces.

Something like this

app.filter('formatText', function (){
  return function(input) {
    if(!input) return input;
    var output = input
      //replace possible line breaks.
      .replace(/(\r\n|\r|\n)/g, '<br/>')
      //replace tabs
      .replace(/\t/g, '&nbsp;&nbsp;&nbsp;')
      //replace spaces.
      .replace(/ /g, '&nbsp;');

      return output;
  };
});

Then to use it you'd do something like this:

<span ng-bind-html="foo | formatText"></span>

Important to note:

  1. You'll need to include the angular-sanitize.js file in your script references.
  2. You'll need to require 'ngSanitize' in your module declaration:
var app = angular.module('myApp', ['ngSanitize']);

.. this is so you can use the ng-bind-html or ng-bind-html-unsafe directives.

Here is a plunk that demonstrates the usage.

1 Comment

This is nice, but the text is not wrapping
7

As other answer mentioned, you can use a filter to achieve it.

Let me implement it for you:

<textarea ng-model="StringValue"></textarea>
<div ng-bind-html-unsafe="StringValue | breakFilter"></div>

angular.module('myApp', []).filter('breakFilter', function () {
    return function (text) {
        if (text !== undefined) return text.replace(/\n/g, '<br />');
    };
});

Comments

2

You can always use a PRE tag:

<textarea ng-model="StringValue"></textarea>
<pre>{{StringValue}}</pre>

Another way you might do it:

<textarea ng-model="StringValue"></textarea>
<span ng-bind-html-unsafe="newLineToBR(StringValue)"></span>

with a controller function:

$scope.newLineToBR = function(text) {
    return text ? text.replace(/\n/g, '<br />') : '';
};

Or, a better approach, as @sza shows, is to turn it into a filter. Here is a working example.

Comments

2

The proper, simplest, semantically correct way to handle your situation is to use a pre tag. These tags are specifically designed for already formatted text, which is what you have here. Text in pre tags can easily be styled to look like normal text using CSS.

<pre style="font: inherit">{{StringValue}}</pre>

Comments

1

Don't ask me why but for the replace to work I had to have an extra \ in front of the \n

input.replace(/\\n/g, '<br />')

Comments

0

You can use a filter to convert new-lines \n to html breaks.

{{StringValue | breakFilter}}

Comments

0

If you use Angular

you can use [innerText] Or [innerHTML] It just like this

<p  [innerText]=StringValue /p>

1 Comment

It shows everything in 1 line

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.