Ahmet Ekrem SABAN
asked on
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
The teaser may include HTML formating or elements like the &. 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:
Thank you for your answer!
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>
The teaser may include HTML formating or elements like the &. 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.
});
}
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>
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!
ASKER
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!!
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!!
Would an outer ng-repeat that loops through the array help here?
ASKER
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 & Outdoor".
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:
and in the view, reference "processHtml(myHTML)".
Something like this:
$scope.processHtml = function(html) {
// Combine HTML
return combinedHTML
}
and in the view, reference "processHtml(myHTML)".
ASKER
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>
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?
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>
<p>{{myHTML[$index]}}</p>
becomes
<p>{{processHtml(myHTML)}}
ASKER
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>
[...]
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
}
[...]
Waking up too early means too hasty:
<p>{{processHtml(myHTML)}} </p>
becomes
<p ng-bind-html="processHtml( myHtml)" />
<p>{{processHtml(myHTML)}}
becomes
<p ng-bind-html="processHtml(
ASKER
Good morning, then! :-D
We are approaching! Now, the only unknown is combinedHTML in the processHTML function...
We are approaching! Now, the only unknown is combinedHTML in the processHTML function...
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.
ASKER
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.
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.
2) The debugger indicates that the "html" variable is undefined, which would point to a problem in the view.
ASKER
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
But the all news page runs with the loop that replaces the new line from my last post with
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.)
(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
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>
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(
(Most probably, I will return on Monday to work.)
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].
ASKER
Hello!
Thank you for your reply! Instead of
Thank you for your reply! Instead of
<article ng-bind-html="my in myHTML">
<p>{{my}}</p>
<p ng-bind-html="processHTML(anHTML)" />
</article>
, 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:ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
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>
What problem are you seeing with ng-bind-html? Are you looking for something like ng-bind-html-unsafe (or $sce.trustAsHtml)?