I’ve run into this issue multiple times while working with AngularJS 1.x, and I’m sure you’ve probably seen it too. You generate some HTML inside your controller thinking Angular will magically render it only to end up with your HTML displayed as text instead of actual markup.
Let me walk you through exactly why this happens and how I fixed it, along with an improved version that lets you render dynamic HTML from JSON data.
The Problem: Angular Won’t Render My HTML String
Here’s the code I started with pretty straightforward.
Controller
var SomeController = function ($scope) {
$scope.customHtml = '<ul><li>render me please</li></ul>';
}
View
<div ng-bind="customHtml"></div>
Result
<div>
"<ul><li>render me please</li></ul>"
</div>
Angular literally printed the HTML as text including the quotes.
Why Does Angular Escape My HTML
It turns out, Angular is being protective on purpose.
By default, directives like ng-bind
or {{ customHtml }}
sanitize and escape any HTML to prevent XSS (Cross-Site Scripting) attacks.
So unless I explicitly tell Angular that my HTML is safe, it will never render dynamic markup.
Mark the HTML as Trusted Using $sce.trustAsHtml
AngularJS provides a special service called $sce (Strict Contextual Escaping). I can pass my HTML string through it to let Angular know I trust the content.
Corrected Controller
var SomeController = function ($scope, $sce) {
$scope.customHtml = $sce.trustAsHtml('<ul><li>Rendered through trustAsHtml</li></ul>');
}
Updated View
<div ng-bind-html="customHtml"></div>
Important: Include ngSanitize
or This Won’t Work
Make sure to include the sanitize module:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular-sanitize.js"></script>
Then inject it into your app:
angular.module('myApp', ['ngSanitize']);
Convert JSON to Dynamic HTML
Let’s go one step further. I had a messy JSON blob coming from an API, and I wanted to turn it into a readable list.
Example JSON
$scope.data = { id: 1, name: "Alice", age: 25 };
Enhanced Controller Logic
$scope.generateHtml = function () {
let html = '<ul>';
angular.forEach($scope.data, function(value, key) {
html += `<li>${key}: ${value}</li>`;
});
html += '</ul>';
$scope.customHtml = $sce.trustAsHtml(html);
}
View
<button ng-click="generateHtml()">Generate HTML</button>
<div ng-bind-html="customHtml"></div>
Now I can dynamically render lists from any JSON object — neat and readable.
Final Thought
Working with AngularJS can sometimes feel restrictive, especially when it refuses to render HTML the way we expect. But once I realized it’s doing this to keep my app secure, everything clicked. With just a small tweak using $sce.trustAsHtml
, I not only fixed the issue but unlocked full control over dynamic HTML rendering. Sometimes, the best solutions aren’t about fighting the framework they’re about understanding it.