[javascript] AngularJS is rendering <br> as text not as a newline

I am sure this has been asked before but I cannot find the answer.

I have an AngularJS script that is pulling from a DB and then rendering to content. Everything is working correctly except a couple of places that I am trying to concatenate some words with new lines between them.

 **in the script.js**
groupedList[aIndex].CATEGORY = existingCategory+'\n'+thisCategory;
groupedList[aIndex].CATEGORY = existingCategory+'<br>'+thisCategory;

If I use the first line of the above code I don't see anything but there is not a new line in the redered html. If I use the second line the <br> get rendered as text and the output looks like this:

Instinct<br>Media

instead of

Instinct
Media

I can post the full script if that would be helpful but I am guessing there is something simple that I am just not seeing.

UPDATE Here is the full js

function qCtrl($scope, $filter, $http, $timeout){

    $scope.getCategories = function(){$http.post('quote.cfc?method=getCategories').success(function(data) { $scope.categories = data; });   }
    $scope.getClassifications = function(){$http.post('quote.cfc?method=getClassifications').success(function(data) {   $scope.classifications = data;  }); }
    $scope.getIndustries = function(){$http.post('quote.cfc?method=getIndustries').success(function(data) { $scope.industries = data;   }); }
    $scope.getKeywords = function(){$http.post('quote.cfc?method=getKeywords').success(function(data) { $scope.keywords = data; }); }
    $scope.getSources = function(){$http.post('quote.cfc?method=getSources').success(function(data) {   $scope.sources = data;  }); }

    $scope.getAllQuotes = function(){$http.post('quote.cfc?method=getAllQuotesJoined').success(function(data) { $scope.allQuotes = data;    }); }

    $scope.initScopes = function (){
        $scope.getCategories();
        $scope.getClassifications();
        $scope.getIndustries();
        $scope.getKeywords();
        $scope.getSources();
        $scope.getAllQuotes();
    }   
    $scope.initScopes();

    // SEARCH QUOTES
    $scope.filteredQuotes = $scope.allQuotes;
    $scope.search = {searchField:''};

    $scope.searchQuote = function(){
        var filter = $filter('filter');
        var searchCrit = $scope.search;
        var newlist = $scope.allQuotes;
        var groupedList = [];
        var idList = [];
        newlist = filter(newlist,{TESTQUOTE:searchCrit.searchField});
        for(i=0;i<10;i++){
            aIndex = idList.contains(newlist[i].TESTIMONIALID);
            if(aIndex >= 0){
                thisKeyword = newlist[i].KEYWORD;
                thisClassification = newlist[i].CLASSIFICATION;
                thisCategory = newlist[i].CATEGORY;
                existingKeyword = groupedList[aIndex].KEYWORD;
                existingClassification = groupedList[aIndex].CLASSIFICATION;
                existingCategory = groupedList[aIndex].CATEGORY;
                if(thisKeyword != '' && existingKeyword.indexOf(thisKeyword) == -1){
                    groupedList[aIndex].KEYWORD = existingKeyword+' - '+thisKeyword;
                } 
                if(thisClassification != '' && existingClassification.indexOf(thisClassification) == -1){
                    groupedList[aIndex].CLASSIFICATION = existingClassification+' \n '+thisClassification;
                } 
                if(thisCategory != '' && existingCategory.indexOf(thisCategory) == -1){
                    groupedList[aIndex].CATEGORY = existingCategory+'<br>'+thisCategory;
                }               
            } else {
                idList.push(newlist[i].TESTIMONIALID);
                groupedList.push(newlist[i]);
            }
        }
        $scope.filteredQuotes = groupedList;
      }
}
Array.prototype.contains = function ( needle ) {
   for (j in this) {
       if (this[j] == needle) return j;
   }
   return -1;
}

Here is the HTML

<div ng-repeat="q in filteredQuotes" class="well clearfix">
                        <h3>{{q.TITLE}}</h3>
                        <div class="row-fluid" style="margin-bottom:5px;">
                            <div class="span3 well-small whBG"><h4>Classification</h4>{{q.CLASSIFICATION}}</div>
                            <div class="span3 well-small whBG pipeHolder"><h4>Categories</h4>{{q.CATEGORY}}</div>
                            <div class="span3 well-small whBG"><h4>Key Words</h4>{{q.KEYWORD}}</div>
                            <div class="span3 well-small whBG"><h4>Additional</h4>Industry = {{q.INDUSTRY}}<br>Source = {{q.SOURCE}}</div>
                        </div>
                        <div class="well whBG">{{q.TESTQUOTE}}</div>
                        <div class="tiny">
                            Source comment : {{q.SOURCECOMMENT}}<br>
                            Additional Comment : {{q.COMMENT}}
                        </div>
                    </div>
                </div>

This question is related to javascript angularjs

The answer is


You need to either use ng-bind-html-unsafe ... or you need to include the ngSanitize module and use ng-bind-html:

with ng-bind-html-unsafe

Use this if you trust the source of the HTML you're rendering it will render the raw output of whatever you put into it.

<div><h4>Categories</h4><span ng-bind-html-unsafe="q.CATEGORY"></span></div>

OR with ng-bind-html

Use this if you DON'T trust the source of the HTML (i.e. it's user input). It will sanitize the html to make sure it doesn't include things like script tags or other sources of potential security risks.

Make sure you include this:

<script src="http://code.angularjs.org/1.0.4/angular-sanitize.min.js"></script>

Then reference it in your application module:

var app = angular.module('myApp', ['ngSanitize']);

THEN use it:

<div><h4>Categories</h4><span ng-bind-html="q.CATEGORY"></span></div>

I've used like this

function chatSearchCtrl($scope, $http,$sce) {
 // some more my code

// take this 
data['message'] = $sce.trustAsHtml(data['message']);

$scope.searchresults = data;

and in html I did

<p class="clsPyType clsChatBoxPadding" ng-bind-html="searchresults.message"></p>

thats it I get my <br/> tag rendered


You can use \n to concatenate words and then apply this style to container div.

style="white-space: pre;"

More info can be found at https://developer.mozilla.org/en-US/docs/Web/CSS/white-space

_x000D_
_x000D_
<p style="white-space: pre;">_x000D_
    This is normal text._x000D_
</p>_x000D_
<p style="white-space: pre;">_x000D_
    This _x000D_
  text _x000D_
  contains _x000D_
  new lines._x000D_
</p>
_x000D_
_x000D_
_x000D_


Why so complicated?

I solved my problem this way simply:

  <pre>{{existingCategory+thisCategory}}</pre>

It will make <br /> automatically if the string contains '\n' that contain when I was saving data from textarea.