How to parse HTML content of a variable in Angular.JS?

Hello!

I am new to Angular.JS & are currently working on my first project. I have a page full of entries of the kind
<h1>Title</h1>
<p>Teaser</p>
<p>(a link)</p>

Open in new window


The teaser may include HTML formating or elements like the &amp;. What I want to do is to "parse" this Teaser so that the formating is "understood" properly by the browser (currently Google Chrome).

For the detail page, an id is passed to the shownews, but the first call is without an id to read all the news from where, the user can reach the detail page by each news link. Here, I already head the same problem. Below, you see the Angular.JS code for both the main news page and the detail page. I could solve the problem for the detail page by using the ng-bind-html directive as follows:
controllers.js:
	$scope.shownews = function(id) {

		if (typeof id === 'undefined') {
			$http({
				method: 'GET',
				url: 'http://dev.ivm.at/getallnews.php'
			}).
				success(function(data, status, headers, config) {
					$scope.allnews = data;
					$scope.myHTML = [];

					for (var i = 0; i < $scope.allnews.length; i++) {
						$scope.myHTML[i] = $scope.allnews[i].Teaser;
					}
				});
		} else {
			$http({
				method: 'GET',
				url: 'http://dev.ivm.at/getnews.php?ID=' + id
			}).
				success(function(data, status, headers, config) {
					$scope.singlenews = data;
					$scope.Newstitel = $scope.singlenews[0].Title
					$scope.Bilderlink = $scope.singlenews[0].Bilderlink;
					$scope.Inhalt = $scope.singlenews[0].Inhalt;
					$scope.Teaser = $scope.singlenews[0].Teaser;

					$scope.myHTML = '<h1>' + $scope.Newstitel + '</h1><br>'
						+ '<a href="lighbox mit bild"></a><img alt="" src="'
						+ $scope.Bilderlink + '"><br>'
						/*+ '" style="width:20%;height:20%"><br>'*/
						+ $scope.Inhalt + '</p>';
					//Bilderlink = "http://dev.ivm.at/IVM_APP/uploadlive/graz.JPG"
					//$scope.Bilderlink = $scope.singlenews[0].Bilderlink;
					//usw.
					//Im Array immer 0 weil das der richtige und einzige Datensatz ist.
				});
		}

Open in new window

index.html:
<div data-role="page" id="allnews">
  <div id="sub">
    <section class="blog">
      <article ng-bind-html="myHTML" ng-repeat="news in allnews">
        <h1>{{news.Title}}</h1>
        <p>{{myHTML[$index]}}</p>
        <p class="readmore">
          <a href="onenews" ng-click="shownews(news.ID)">
                  Weiterlesen: {{news.Title}}
          </a>
          <span class="readmore_icon"></span>
        </p>
      </article>
    </section>
  </div>
</div>

Open in new window

My question is how to use the ng-bind-html command properly so that it does parse the $scope.myHTML in the case it is an array of texts.

Thank you for your answer!
LVL 1
Ahmet Ekrem SABANSenior IT consultantAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Bob LearnedCommented:
I am confused about the real intent for your question between "What I want to do is to "parse" this Teaser so that the formating is "understood" properly by the browser (currently Google Chrome)." and "so that it does parse the $scope.myHTML in the case it is an array of texts."

What problem are you seeing with ng-bind-html?  Are you looking for something like ng-bind-html-unsafe (or  $sce.trustAsHtml)?
0
Ahmet Ekrem SABANSenior IT consultantAuthor Commented:
Thank you for your reply!

The problem is not that ng-bind-html is not working at all. It is working when $scope.myHTML is a string. What I need is a solution that converts the contents of this variable to HTML when it is an array of strings!!
0
Bob LearnedCommented:
Would an outer ng-repeat that loops through the array help here?
0
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

Ahmet Ekrem SABANSenior IT consultantAuthor Commented:
If it could be possible to change the array contents to HTML, it would. :) What I do not want is to see text like "Home &amp; Outdoor".
0
Bob LearnedCommented:
If I understand you correctly, I would think that you could create a function in the controller, and process the array, and return a string.

Something like this:

$scope.processHtml = function(html) {
     // Combine HTML
     return combinedHTML
}

Open in new window


and in the view, reference "processHtml(myHTML)".
0
Ahmet Ekrem SABANSenior IT consultantAuthor Commented:
Thank you for your reply! I added your function to the controller as it is. Here is the code where the myHTML array is accessed, and where I am supposed to use it:
<!-- All news page -->
<div data-role="page" id="allnews">
	<div id="sub">
		<section class="blog">
			<article ng-repeat="news in allnews">
				<h1>{{news.Title}}</h1>
				<p>{{news.Teaser}}</p>
				<p>{{myHTML[$index]}}</p>
				<p class="readmore">
					<a href="#news" ng-click="shownews(news.ID);">
						Weiterlesen: {{news.Title}}
					</a>
					<span class="readmore_icon"></span>
				</p>
			</article>
		</section>
	</div>
</div>

Open in new window

The line with the index is <p>{{myHTML[$index]}}</p>. How do I have to call the function here? As a property of the article tag?
0
Bob LearnedCommented:
If you add the function to the scope, you should be able to use it like this:

<p>{{myHTML[$index]}}</p>

         becomes

<p>{{processHtml(myHTML)}}</p>
0
Ahmet Ekrem SABANSenior IT consultantAuthor Commented:
Here are the results...
[...]
<div data-role="page" id="allnews">
	<div id="sub">
		<section class="blog">
			<article ng-repeat="news in allnews">
				<h1>{{news.Title}}</h1>
				<p>{{news.Teaser}}</p>
				<p>{{processHTML(myHTML)}}</p>
				<p class="readmore">
					<a href="#news" ng-click="shownews(news.ID);">
						Weiterlesen: {{news.Title}}
					</a>
					<span class="readmore_icon"></span>
				</p>
			</article>
		</section>
	</div>
</div>
[...]

Open in new window

app.controller("PostsCtrl", function($scope, $http) {
	$http.defaults.useXDomain = true;
	delete $http.defaults.headers.common['X-Requested-With'];

	$scope.processHTML = function(html) {
		// Combine HTML
		return combinedHTML
	}
	[...]

Open in new window

Result page for "all news"
0
Bob LearnedCommented:
Waking up too early means too hasty:

<p>{{processHtml(myHTML)}}</p>

    becomes

<p ng-bind-html="processHtml(myHtml)" />
0
Ahmet Ekrem SABANSenior IT consultantAuthor Commented:
Good morning, then! :-D

We are approaching! Now, the only unknown is combinedHTML in the processHTML function...
0
Bob LearnedCommented:
I was guessing at a variable name that you could use to combine the HTML that is in the array.  You could use Array.isArray on the input variable to determine if it is an array, and then use for loop to process each of the HTML elements in the array, and build "combinedHtml".  If the input is a string, just return that value.
0
Ahmet Ekrem SABANSenior IT consultantAuthor Commented:
Oh, I know what you mean: $scope.myHTML, which is either a string or an array of strings, both with or without HTML tags. I can see in the debugger that the array is returned back by your function, but the information cannot be shown by the browser (Google Chrome). You see, what I need is the content of this array and parsed as HTML.
The management info, which was processHTML before is now missingThe management info, which was processHTML before, is now missing
0
Bob LearnedCommented:
1) You would need to loop through each element in the array, and build a string, that you could return.

2) The debugger indicates that the "html" variable is undefined, which would point to a problem in the view.
0
Ahmet Ekrem SABANSenior IT consultantAuthor Commented:
OK. I sent you only a part of the code. There is an error message for a missing image and another message that is repeated a lot of times that reads
(257) angular.js:5601 TypeError: a.replace is not a function
    at k (angular-sanitize.min.js:8)
    at z (angular-sanitize.min.js:7)
    at angular-sanitize.min.js:12
    at Object.fn (angular-sanitize.min.js:12)
    at Object.$get.Scope.$digest (angular.js:7790)
    at Object.$get.Scope.$apply (angular.js:7991)
    at done (angular.js:9001)
    at completeRequest (angular.js:9141)
    at XMLHttpRequest.xhr.onreadystatechange (angular.js:9111)(anonymous function) @ angular.js:5601$get @ angular.js:4698$get.Scope.$digest @ angular.js:7802$get.Scope.$apply @ angular.js:7991done @ angular.js:9001completeRequest @ angular.js:9141xhr.onreadystatechange @ angular.js:9111

Open in new window

As there is no reference to my code, I do not know what is the reason for it.

But the all news page runs with the loop that replaces the new line from my last post with
	<article ng-repeat="anHTML in myHTML">
		<!-- p>{{anHTML}}</p -->
		<p ng-bind-html="processHTML(anHTML)" />
	</article>

Open in new window

I added the first line of the loop for test purposes to see, if something is output. Well, the whole array content is output. But the processHTML line does nothing. :-S Now, we are at that point what made me ask for help.

The important point is that, if processHTML would work in this loop properly, I still need a call of the kind <p ng-bind-html="processHTML($index)" /> without a loop, as only one element of the index is required for each news synopsis.

(Most probably, I will return on Monday to work.)
0
Bob LearnedCommented:
Is this repeat going to always have an array?  Are you always going to next the n-th element from the array?  If so, then I would think that you get away with an ng-bind-html with myHtml[$index].
0
Ahmet Ekrem SABANSenior IT consultantAuthor Commented:
Hello!

Thank you for your reply! Instead of
<article ng-bind-html="my in myHTML">
	<p>{{my}}</p>
	<p ng-bind-html="processHTML(anHTML)" />
</article>

Open in new window

, I tried the following:

<article ng-repeat="news in allnews"> <h1>{{news.Title}}</h1> <p>{{news.Teaser}}</p> <p ng-bind-html="process(myHTML[$index])"></p> <p class="readmore"> <a href="#news" ng-click="shownews(news.ID);"> Weiterlesen: {{news.Title}} </a> <span class="readmore_icon"></span> </p> </article>
<article ng-repeat="news in allnews"> <h1>{{news.Title}}</h1> <p>{{news.Teaser}}</p> <p ng-bind-html="process($scope.myHTML[$index])"></p> <p class="readmore"> <a href="#news" ng-click="shownews(news.ID);"> Weiterlesen: {{news.Title}} </a> <span class="readmore_icon"></span> </p> </article>
<article ng-repeat="news in allnews"> <h1>{{news.Title}}</h1> <p>{{news.Teaser}}</p> <p>{{$scope.myHTML[$index]}}</p> <p ng-bind-html="process($scope.myHTML[$index])"></p> <p class="readmore"> <a href="#news" ng-click="shownews(news.ID);"> Weiterlesen: {{news.Title}} </a> <span class="readmore_icon"></span> </p> </article>
But I couldn't get what I wanted. It was always like this with the missing third line before the link at the bottom:
The result
0
Bob LearnedCommented:
Let's try this instead:

1) You set "myHTML" in this loop:

for (var i = 0; i < $scope.allnews.length; i++) {
						$scope.myHTML[i] = $scope.allnews[i].Teaser;
					}

Open in new window


2) You have this ng-repeat:

<article ng-repeat="news in allnews">

3) Use the "news" instead:

<p ng-bind-html="news.Teaser"></p>
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Ahmet Ekrem SABANSenior IT consultantAuthor Commented:
Bingo!!!! That is the right answer!

<div data-role="page" id="allnews">
	<div id="sub">
		<section class="blog">
			<article ng-repeat="news in allnews">
				<h1>{{news.Title}}</h1>
				<p ng-bind-html="news.Teaser"></p>
				[...]
			</article>
		</section>
	</div>
</div>

Open in new window

0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
JavaScript

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.