Is it possible to create an HTML fragment in an AngularJS controller and have this HTML shown in the view?
This comes from a requirement to turn an inconsistent JSON blob into a nested list of id: value pairs. Therefore the HTML is created in the controller and I am now looking to display it.
I have created a model property, but cannot render this in the view without it just printing the HTML.
Update
It appears that the problem arises from angular rendering the created HTML as a string within quotes. Will attempt to find a way around this.
Example controller :
var SomeController = function () {
this.customHtml = '<ul><li>render me please</li></ul>';
}
Example view :
<div ng:bind="customHtml"></div>
Gives :
<div>
"<ul><li>render me please</li></ul>"
</div>
For Angular 1.x, use ng-bind-html in the HTML:
<div ng-bind-html="thisCanBeusedInsideNgBindHtml"></div>
At this point you would get a attempting to use an unsafe value in a safe context error so you need to either use ngSanitize or $sce to resolve that.
$sce
Use $sce.trustAsHtml() in the controller to convert the html string.
$scope.thisCanBeusedInsideNgBindHtml = $sce.trustAsHtml(someHtmlVar);
ngSanitize
There are 2 steps:
include the angular-sanitize.min.js resource, i.e.:
<script src="lib/angular/angular-sanitize.min.js"></script>
In a js file (controller or usually app.js), include ngSanitize, i.e.:
angular.module('myApp', ['myApp.filters', 'myApp.services',
'myApp.directives', 'ngSanitize'])
You can also create a filter like so:
var app = angular.module("demoApp", ['ngResource']);
app.filter("trust", ['$sce', function($sce) {
return function(htmlCode){
return $sce.trustAsHtml(htmlCode);
}
}]);
Then in the view
<div ng-bind-html="trusted_html_variable | trust"></div>
Note: This filter trusts any and all html passed to it, and could present an XSS vulnerability if variables with user input are passed to it.
Angular JS shows HTML within the tag
The solution provided in the above link worked for me, none of the options on this thread did. For anyone looking for the same thing with AngularJS version 1.2.9
Here's a copy:
Ok I found solution for this:
JS:
$scope.renderHtml = function(html_code)
{
return $sce.trustAsHtml(html_code);
};
HTML:
<p ng-bind-html="renderHtml(value.button)"></p>
EDIT:
Here's the set up:
JS file:
angular.module('MyModule').controller('MyController', ['$scope', '$http', '$sce',
function ($scope, $http, $sce) {
$scope.renderHtml = function (htmlCode) {
return $sce.trustAsHtml(htmlCode);
};
$scope.body = '<div style="width:200px; height:200px; border:1px solid blue;"></div>';
}]);
HTML file:
<div ng-controller="MyController">
<div ng-bind-html="renderHtml(body)"></div>
</div>
Fortunately, you don't need any fancy filters or unsafe methods to avoid that error message. This is the complete implementation to properly output HTML markup in a view in the intended and safe way.
The sanitize module must be included after Angular:
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular-sanitize.js"></script>
Then, the module must be loaded:
angular.module('app', [
'ngSanitize'
]);
This will allow you to include markup in a string from a controller, directive, etc:
scope.message = "<strong>42</strong> is the <em>answer</em>.";
Finally, in a template, it must be output like so:
<p ng-bind-html="message"></p>
Which will produce the expected output: 42 is the answer.
I have tried today, the only way I found was this
<div ng-bind-html-unsafe="expression"></div>
ng-bind-html-unsafe no longer works.
This is the shortest way:
Create a filter:
myApp.filter('unsafe', function($sce) { return $sce.trustAsHtml; });
And in your view:
<div ng-bind-html="customHtml | unsafe"></div>
P.S. This method doesn't require you to include the ngSanitize module.
on html
<div ng-controller="myAppController as myCtrl">
<div ng-bind-html-unsafe="myCtrl.comment.msg"></div>
OR
<div ng-bind-html="myCtrl.comment.msg"></div
on controller
mySceApp.controller("myAppController", function myAppController( $sce) {
this.myCtrl.comment.msg = $sce.trustAsHtml(html);
works also with $scope.comment.msg = $sce.trustAsHtml(html);
I found that using ng-sanitize did not allow me to add ng-click in the html.
To solve this I added a directive. Like this:
app.directive('htmldiv', function($compile, $parse) {
return {
restrict: 'E',
link: function(scope, element, attr) {
scope.$watch(attr.content, function() {
element.html($parse(attr.content)(scope));
$compile(element.contents())(scope);
}, true);
}
}
});
And this is the HTML:
<htmldiv content="theContent"></htmldiv>
Good luck.
Just did this using ngBindHtml by following angular(v1.4) docs,
<div ng-bind-html="expression"></div>
and expression can be "<ul><li>render me please</li></ul>"
Make sure you include ngSanitize in the module's dependencies.
Then it should work fine.
Another solution, very similar to blrbr's except using a scoped attribute is:
angular.module('app')
.directive('renderHtml', ['$compile', function ($compile) {
return {
restrict: 'E',
scope: {
html: '='
},
link: function postLink(scope, element, attrs) {
function appendHtml() {
if(scope.html) {
var newElement = angular.element(scope.html);
$compile(newElement)(scope);
element.append(newElement);
}
}
scope.$watch(function() { return scope.html }, appendHtml);
}
};
}]);
And then
<render-html html="htmlAsString"></render-html>
Note you may replace element.append() with element.replaceWith()
there is one more solution for this problem using creating new attribute or directives in angular.
product-specs.html
<h4>Specs</h4>
<ul class="list-unstyled">
<li>
<strong>Shine</strong>
: {{product.shine}}</li>
<li>
<strong>Faces</strong>
: {{product.faces}}</li>
<li>
<strong>Rarity</strong>
: {{product.rarity}}</li>
<li>
<strong>Color</strong>
: {{product.color}}</li>
</ul>
app.js
(function() {
var app = angular.module('gemStore', []);
app.directive(" <div ng-show="tab.isSet(2)" product-specs>", function() {
return {
restrict: 'E',
templateUrl: "product-specs.html"
};
});
index.html
<div>
<product-specs> </product-specs>//it will load product-specs.html file here.
</div>
or
<div product-specs>//it will add product-specs.html file
or
<div ng-include="product-description.html"></div>
https://docs.angularjs.org/guide/directive
you can also use ng-include.
<div class="col-sm-9 TabContent_container" ng-include="template/custom.html">
</div>
you can use "ng-show" to show hide this template data.
here is the solution make a filter like this
.filter('trusted',
function($sce) {
return function(ss) {
return $sce.trustAsHtml(ss)
};
}
)
and apply this as a filter to the ng-bind-html like
<div ng-bind-html="code | trusted">
and thank to Ruben Decrop
Use
<div ng-bind-html="customHtml"></div>
and
angular.module('MyApp', ['ngSanitize']);
For that, you need to include angular-sanitize.js,
for example in your html-file with
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular-sanitize.js"></script>
Here's a simple (and unsafe) bind-as-html directive, without the need for ngSanitize:
myModule.directive('bindAsHtml', function () {
return {
link: function (scope, element, attributes) {
element.html(scope.$eval(attributes.bindAsHtml));
}
};
});
Note that this will open up for security issues, if binding untrusted content.
Use like so:
<div bind-as-html="someHtmlInScope"></div>
Working example with pipe to display html in template with Angular 4.
1.Crated Pipe escape-html.pipe.ts
`
import { Pipe, PipeTransform } from '#angular/core';
import { DomSanitizer } from '#angular/platform-browser';
#Pipe({name : 'keepHtml', pure : false})
export class EscapeHtmlPipe implements PipeTransform{
constructor(private sanitizer : DomSanitizer){
}
transform(content){
return this.sanitizer.bypassSecurityTrustHtml(content);
}
}
`
2. Register pipe to app.module.ts
import {EscapeHtmlPipe} from './components/pipes/escape-html.pipe';
declarations: [...,EscapeHtmlPipe]
Use in your template
<div class="demoPipe" [innerHtml]="getDivHtml(obj.header) | keepHtml">
getDivHtml() { //can return html as per requirement}
Please add appropriate implementation for getDivHtml in associated component.ts file.
Just simple use [innerHTML], like below:
<div [innerHTML]="htmlString"></div>
Before you needed to use ng-bind-html...
Related
Is it possible to create an HTML fragment in an AngularJS controller and have this HTML shown in the view?
This comes from a requirement to turn an inconsistent JSON blob into a nested list of id: value pairs. Therefore the HTML is created in the controller and I am now looking to display it.
I have created a model property, but cannot render this in the view without it just printing the HTML.
Update
It appears that the problem arises from angular rendering the created HTML as a string within quotes. Will attempt to find a way around this.
Example controller :
var SomeController = function () {
this.customHtml = '<ul><li>render me please</li></ul>';
}
Example view :
<div ng:bind="customHtml"></div>
Gives :
<div>
"<ul><li>render me please</li></ul>"
</div>
For Angular 1.x, use ng-bind-html in the HTML:
<div ng-bind-html="thisCanBeusedInsideNgBindHtml"></div>
At this point you would get a attempting to use an unsafe value in a safe context error so you need to either use ngSanitize or $sce to resolve that.
$sce
Use $sce.trustAsHtml() in the controller to convert the html string.
$scope.thisCanBeusedInsideNgBindHtml = $sce.trustAsHtml(someHtmlVar);
ngSanitize
There are 2 steps:
include the angular-sanitize.min.js resource, i.e.:
<script src="lib/angular/angular-sanitize.min.js"></script>
In a js file (controller or usually app.js), include ngSanitize, i.e.:
angular.module('myApp', ['myApp.filters', 'myApp.services',
'myApp.directives', 'ngSanitize'])
You can also create a filter like so:
var app = angular.module("demoApp", ['ngResource']);
app.filter("trust", ['$sce', function($sce) {
return function(htmlCode){
return $sce.trustAsHtml(htmlCode);
}
}]);
Then in the view
<div ng-bind-html="trusted_html_variable | trust"></div>
Note: This filter trusts any and all html passed to it, and could present an XSS vulnerability if variables with user input are passed to it.
Angular JS shows HTML within the tag
The solution provided in the above link worked for me, none of the options on this thread did. For anyone looking for the same thing with AngularJS version 1.2.9
Here's a copy:
Ok I found solution for this:
JS:
$scope.renderHtml = function(html_code)
{
return $sce.trustAsHtml(html_code);
};
HTML:
<p ng-bind-html="renderHtml(value.button)"></p>
EDIT:
Here's the set up:
JS file:
angular.module('MyModule').controller('MyController', ['$scope', '$http', '$sce',
function ($scope, $http, $sce) {
$scope.renderHtml = function (htmlCode) {
return $sce.trustAsHtml(htmlCode);
};
$scope.body = '<div style="width:200px; height:200px; border:1px solid blue;"></div>';
}]);
HTML file:
<div ng-controller="MyController">
<div ng-bind-html="renderHtml(body)"></div>
</div>
Fortunately, you don't need any fancy filters or unsafe methods to avoid that error message. This is the complete implementation to properly output HTML markup in a view in the intended and safe way.
The sanitize module must be included after Angular:
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular-sanitize.js"></script>
Then, the module must be loaded:
angular.module('app', [
'ngSanitize'
]);
This will allow you to include markup in a string from a controller, directive, etc:
scope.message = "<strong>42</strong> is the <em>answer</em>.";
Finally, in a template, it must be output like so:
<p ng-bind-html="message"></p>
Which will produce the expected output: 42 is the answer.
I have tried today, the only way I found was this
<div ng-bind-html-unsafe="expression"></div>
ng-bind-html-unsafe no longer works.
This is the shortest way:
Create a filter:
myApp.filter('unsafe', function($sce) { return $sce.trustAsHtml; });
And in your view:
<div ng-bind-html="customHtml | unsafe"></div>
P.S. This method doesn't require you to include the ngSanitize module.
on html
<div ng-controller="myAppController as myCtrl">
<div ng-bind-html-unsafe="myCtrl.comment.msg"></div>
OR
<div ng-bind-html="myCtrl.comment.msg"></div
on controller
mySceApp.controller("myAppController", function myAppController( $sce) {
this.myCtrl.comment.msg = $sce.trustAsHtml(html);
works also with $scope.comment.msg = $sce.trustAsHtml(html);
I found that using ng-sanitize did not allow me to add ng-click in the html.
To solve this I added a directive. Like this:
app.directive('htmldiv', function($compile, $parse) {
return {
restrict: 'E',
link: function(scope, element, attr) {
scope.$watch(attr.content, function() {
element.html($parse(attr.content)(scope));
$compile(element.contents())(scope);
}, true);
}
}
});
And this is the HTML:
<htmldiv content="theContent"></htmldiv>
Good luck.
Just did this using ngBindHtml by following angular(v1.4) docs,
<div ng-bind-html="expression"></div>
and expression can be "<ul><li>render me please</li></ul>"
Make sure you include ngSanitize in the module's dependencies.
Then it should work fine.
Another solution, very similar to blrbr's except using a scoped attribute is:
angular.module('app')
.directive('renderHtml', ['$compile', function ($compile) {
return {
restrict: 'E',
scope: {
html: '='
},
link: function postLink(scope, element, attrs) {
function appendHtml() {
if(scope.html) {
var newElement = angular.element(scope.html);
$compile(newElement)(scope);
element.append(newElement);
}
}
scope.$watch(function() { return scope.html }, appendHtml);
}
};
}]);
And then
<render-html html="htmlAsString"></render-html>
Note you may replace element.append() with element.replaceWith()
there is one more solution for this problem using creating new attribute or directives in angular.
product-specs.html
<h4>Specs</h4>
<ul class="list-unstyled">
<li>
<strong>Shine</strong>
: {{product.shine}}</li>
<li>
<strong>Faces</strong>
: {{product.faces}}</li>
<li>
<strong>Rarity</strong>
: {{product.rarity}}</li>
<li>
<strong>Color</strong>
: {{product.color}}</li>
</ul>
app.js
(function() {
var app = angular.module('gemStore', []);
app.directive(" <div ng-show="tab.isSet(2)" product-specs>", function() {
return {
restrict: 'E',
templateUrl: "product-specs.html"
};
});
index.html
<div>
<product-specs> </product-specs>//it will load product-specs.html file here.
</div>
or
<div product-specs>//it will add product-specs.html file
or
<div ng-include="product-description.html"></div>
https://docs.angularjs.org/guide/directive
you can also use ng-include.
<div class="col-sm-9 TabContent_container" ng-include="template/custom.html">
</div>
you can use "ng-show" to show hide this template data.
here is the solution make a filter like this
.filter('trusted',
function($sce) {
return function(ss) {
return $sce.trustAsHtml(ss)
};
}
)
and apply this as a filter to the ng-bind-html like
<div ng-bind-html="code | trusted">
and thank to Ruben Decrop
Use
<div ng-bind-html="customHtml"></div>
and
angular.module('MyApp', ['ngSanitize']);
For that, you need to include angular-sanitize.js,
for example in your html-file with
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular-sanitize.js"></script>
Here's a simple (and unsafe) bind-as-html directive, without the need for ngSanitize:
myModule.directive('bindAsHtml', function () {
return {
link: function (scope, element, attributes) {
element.html(scope.$eval(attributes.bindAsHtml));
}
};
});
Note that this will open up for security issues, if binding untrusted content.
Use like so:
<div bind-as-html="someHtmlInScope"></div>
Working example with pipe to display html in template with Angular 4.
1.Crated Pipe escape-html.pipe.ts
`
import { Pipe, PipeTransform } from '#angular/core';
import { DomSanitizer } from '#angular/platform-browser';
#Pipe({name : 'keepHtml', pure : false})
export class EscapeHtmlPipe implements PipeTransform{
constructor(private sanitizer : DomSanitizer){
}
transform(content){
return this.sanitizer.bypassSecurityTrustHtml(content);
}
}
`
2. Register pipe to app.module.ts
import {EscapeHtmlPipe} from './components/pipes/escape-html.pipe';
declarations: [...,EscapeHtmlPipe]
Use in your template
<div class="demoPipe" [innerHtml]="getDivHtml(obj.header) | keepHtml">
getDivHtml() { //can return html as per requirement}
Please add appropriate implementation for getDivHtml in associated component.ts file.
Just simple use [innerHTML], like below:
<div [innerHTML]="htmlString"></div>
Before you needed to use ng-bind-html...
I'm using templates based on my JSON. So, I can't really use my ng-bind-html like I would normally do.
Seems like the only option I have is to use my sanitized html inside an directive.
Looking for similar questions, I couldn't figure it out how to apply in my case.
Yes, I am pretty newbie into angular.
I'm currently receiving this data from my controller:
$scope.safecontainers = $sanitize($scope.containersmsg);
In my html would normally be like this:
<p ng-bind-html="containersmsg"></p>
But I don't want this, I need to use this ng-bind-html inside a directive!
Some people have talked about $compile, but I couldn't really figure it out how to apply in my case.
EDIT:
Based on comments, i'll add more code to help you guys further understand my goal.
Inside my index.html I'm declaring the controllers needed and calling my
<ng-view></ng-view>
Then, based on what I receive, i'll load one view or another:
<div ng-if='setores[0].SetorTema == "1"'>
<theme-one titulo="{{setores[0].SetorNome}}" logo="
{{setores[0].SetorLogo}}" evento="{{evento[0].EventoNome}}">
</theme-one>
// I omitted some of the parameters because they ain't relevant
</div>
My template is like this: (Just a little part of it to avoid much useless code)
<section class="target">
<div class="col-md-6 col-xs-12">
<div class="" ng-repeat="banner in title">
<div class="target-title">{{ banner.BannerLevelTitulo }}
</div>
<div class="target-desc">{{banner.BannerLevelDescricao}}</div>
</div>
</div>
<div class="col-md-6 col-xs-hidden">
<div class="target-image"><img ng-src="{{targetimage}}" alt="">
</div>
</div>
</section>
This is the controller I want my sanitized code.
hotsite.controller('containerController', function($scope, $http, $sanitize)
{
$scope.containers = [];
$scope.containersmsg = '';
$scope.safecontainers = $sanitize($scope.containersmsg);
$http.get('/Admin/rest/getContainer')
.then(function onSuccess(response) {
var data = response.data;
$scope.containers = data;
$scope.containers = response.data.filter(containers =>
containers.ContainerAtivo);
$scope.containersmsg = $scope.containers[0].ContainerDesc;
})
.catch(function onError(response) {
var data = response.data;
console.log(data);
});
});
This is a piece of my directive:
angular.module('hotsiteDirectives', [])
.directive('themeOne', function($compile) {
var ddo = {};
ddo.restrict = "AE";
ddo.transclude = true;
ddo.scope = {
titulo: '#',
...
(a lot of other scope's)
contimg: '#'
};
ddo.templateUrl = 'app/directives/theme-one.html';
return ddo;
})
And yes, I am calling the ngSanitize
var hotsite = angular.module('hotsite',['ngRoute', 'hotsiteDirectives',
'ngSanitize']);
TL;DR
This is how my code looks like inside a directive, with raw html and not rendered:
This is how it works with ng-bind-html, formatted html
If I do put this inside my view
<p ng-bind-html="containersmsg"></p>
It will be alright, all of it working like it should.
BUT, I need to call this only inside my directive, and I don't know how to do it.
So, with this context:
How can I put my sanitized html inside my directive and template?
You don't even have to trust the html to render it using ngBindHtml because the directive already does it for you. You basically need to create a parameter attribute for your directive to hold the html string, so, inside the directive's template, you use ng-bind-html="myParam".
The following snippet implements a simple demonstration of creating a directive that receives and renders an html input parameter that comes from a controller.
angular.module('app', ['ngSanitize'])
.controller('AppCtrl', function($scope) {
$scope.myHtml = '<div><b>Hello!</b> I\'m an <i>html string</i> being rendered dynamicalli by <code>ngBindHtml</code></div>';
})
.directive('myDirective', function() {
return {
template: '<hr><div ng-bind-html="html"></div><hr>',
scope: {
html: '='
}
};
});
<div ng-app="app" ng-controller="AppCtrl">
<my-directive html="myHtml"></my-directive>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular-sanitize.js"></script>
I have a question about custom directive.
Is it possible to
Create a custom directive
provide it with a templateURL attribute and
in template URL make the use of ng-grid attribute ?
I tried it although my grid is not getting rendered properly if declared in template. This is how my template code looks like
<div class="gridStyle" ng-grid="gridOptions">
</div>
and my controller code inside custom directive looks like
treeApp.controller('treeController',function ($scope, $http,TreeFactory) {
console.log("calling controller");
TreeFactory.getTreeData().success(function(data){
$scope.myData = data;
$scope.gridOptions = { data: 'myData' };
});;
and this is how my custom directive looks like
treeApp.directive('ngTree', function(TreeFactory) {
return {
restrict: 'A',
require: '^ngModel',
templateUrl: 'js/angular/templates/ngtree-template.html',
});
Is it possible to create an HTML fragment in an AngularJS controller and have this HTML shown in the view?
This comes from a requirement to turn an inconsistent JSON blob into a nested list of id: value pairs. Therefore the HTML is created in the controller and I am now looking to display it.
I have created a model property, but cannot render this in the view without it just printing the HTML.
Update
It appears that the problem arises from angular rendering the created HTML as a string within quotes. Will attempt to find a way around this.
Example controller :
var SomeController = function () {
this.customHtml = '<ul><li>render me please</li></ul>';
}
Example view :
<div ng:bind="customHtml"></div>
Gives :
<div>
"<ul><li>render me please</li></ul>"
</div>
For Angular 1.x, use ng-bind-html in the HTML:
<div ng-bind-html="thisCanBeusedInsideNgBindHtml"></div>
At this point you would get a attempting to use an unsafe value in a safe context error so you need to either use ngSanitize or $sce to resolve that.
$sce
Use $sce.trustAsHtml() in the controller to convert the html string.
$scope.thisCanBeusedInsideNgBindHtml = $sce.trustAsHtml(someHtmlVar);
ngSanitize
There are 2 steps:
include the angular-sanitize.min.js resource, i.e.:
<script src="lib/angular/angular-sanitize.min.js"></script>
In a js file (controller or usually app.js), include ngSanitize, i.e.:
angular.module('myApp', ['myApp.filters', 'myApp.services',
'myApp.directives', 'ngSanitize'])
You can also create a filter like so:
var app = angular.module("demoApp", ['ngResource']);
app.filter("trust", ['$sce', function($sce) {
return function(htmlCode){
return $sce.trustAsHtml(htmlCode);
}
}]);
Then in the view
<div ng-bind-html="trusted_html_variable | trust"></div>
Note: This filter trusts any and all html passed to it, and could present an XSS vulnerability if variables with user input are passed to it.
Angular JS shows HTML within the tag
The solution provided in the above link worked for me, none of the options on this thread did. For anyone looking for the same thing with AngularJS version 1.2.9
Here's a copy:
Ok I found solution for this:
JS:
$scope.renderHtml = function(html_code)
{
return $sce.trustAsHtml(html_code);
};
HTML:
<p ng-bind-html="renderHtml(value.button)"></p>
EDIT:
Here's the set up:
JS file:
angular.module('MyModule').controller('MyController', ['$scope', '$http', '$sce',
function ($scope, $http, $sce) {
$scope.renderHtml = function (htmlCode) {
return $sce.trustAsHtml(htmlCode);
};
$scope.body = '<div style="width:200px; height:200px; border:1px solid blue;"></div>';
}]);
HTML file:
<div ng-controller="MyController">
<div ng-bind-html="renderHtml(body)"></div>
</div>
Fortunately, you don't need any fancy filters or unsafe methods to avoid that error message. This is the complete implementation to properly output HTML markup in a view in the intended and safe way.
The sanitize module must be included after Angular:
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular-sanitize.js"></script>
Then, the module must be loaded:
angular.module('app', [
'ngSanitize'
]);
This will allow you to include markup in a string from a controller, directive, etc:
scope.message = "<strong>42</strong> is the <em>answer</em>.";
Finally, in a template, it must be output like so:
<p ng-bind-html="message"></p>
Which will produce the expected output: 42 is the answer.
I have tried today, the only way I found was this
<div ng-bind-html-unsafe="expression"></div>
ng-bind-html-unsafe no longer works.
This is the shortest way:
Create a filter:
myApp.filter('unsafe', function($sce) { return $sce.trustAsHtml; });
And in your view:
<div ng-bind-html="customHtml | unsafe"></div>
P.S. This method doesn't require you to include the ngSanitize module.
on html
<div ng-controller="myAppController as myCtrl">
<div ng-bind-html-unsafe="myCtrl.comment.msg"></div>
OR
<div ng-bind-html="myCtrl.comment.msg"></div
on controller
mySceApp.controller("myAppController", function myAppController( $sce) {
this.myCtrl.comment.msg = $sce.trustAsHtml(html);
works also with $scope.comment.msg = $sce.trustAsHtml(html);
I found that using ng-sanitize did not allow me to add ng-click in the html.
To solve this I added a directive. Like this:
app.directive('htmldiv', function($compile, $parse) {
return {
restrict: 'E',
link: function(scope, element, attr) {
scope.$watch(attr.content, function() {
element.html($parse(attr.content)(scope));
$compile(element.contents())(scope);
}, true);
}
}
});
And this is the HTML:
<htmldiv content="theContent"></htmldiv>
Good luck.
Just did this using ngBindHtml by following angular(v1.4) docs,
<div ng-bind-html="expression"></div>
and expression can be "<ul><li>render me please</li></ul>"
Make sure you include ngSanitize in the module's dependencies.
Then it should work fine.
Another solution, very similar to blrbr's except using a scoped attribute is:
angular.module('app')
.directive('renderHtml', ['$compile', function ($compile) {
return {
restrict: 'E',
scope: {
html: '='
},
link: function postLink(scope, element, attrs) {
function appendHtml() {
if(scope.html) {
var newElement = angular.element(scope.html);
$compile(newElement)(scope);
element.append(newElement);
}
}
scope.$watch(function() { return scope.html }, appendHtml);
}
};
}]);
And then
<render-html html="htmlAsString"></render-html>
Note you may replace element.append() with element.replaceWith()
there is one more solution for this problem using creating new attribute or directives in angular.
product-specs.html
<h4>Specs</h4>
<ul class="list-unstyled">
<li>
<strong>Shine</strong>
: {{product.shine}}</li>
<li>
<strong>Faces</strong>
: {{product.faces}}</li>
<li>
<strong>Rarity</strong>
: {{product.rarity}}</li>
<li>
<strong>Color</strong>
: {{product.color}}</li>
</ul>
app.js
(function() {
var app = angular.module('gemStore', []);
app.directive(" <div ng-show="tab.isSet(2)" product-specs>", function() {
return {
restrict: 'E',
templateUrl: "product-specs.html"
};
});
index.html
<div>
<product-specs> </product-specs>//it will load product-specs.html file here.
</div>
or
<div product-specs>//it will add product-specs.html file
or
<div ng-include="product-description.html"></div>
https://docs.angularjs.org/guide/directive
you can also use ng-include.
<div class="col-sm-9 TabContent_container" ng-include="template/custom.html">
</div>
you can use "ng-show" to show hide this template data.
here is the solution make a filter like this
.filter('trusted',
function($sce) {
return function(ss) {
return $sce.trustAsHtml(ss)
};
}
)
and apply this as a filter to the ng-bind-html like
<div ng-bind-html="code | trusted">
and thank to Ruben Decrop
Use
<div ng-bind-html="customHtml"></div>
and
angular.module('MyApp', ['ngSanitize']);
For that, you need to include angular-sanitize.js,
for example in your html-file with
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular-sanitize.js"></script>
Here's a simple (and unsafe) bind-as-html directive, without the need for ngSanitize:
myModule.directive('bindAsHtml', function () {
return {
link: function (scope, element, attributes) {
element.html(scope.$eval(attributes.bindAsHtml));
}
};
});
Note that this will open up for security issues, if binding untrusted content.
Use like so:
<div bind-as-html="someHtmlInScope"></div>
Working example with pipe to display html in template with Angular 4.
1.Crated Pipe escape-html.pipe.ts
`
import { Pipe, PipeTransform } from '#angular/core';
import { DomSanitizer } from '#angular/platform-browser';
#Pipe({name : 'keepHtml', pure : false})
export class EscapeHtmlPipe implements PipeTransform{
constructor(private sanitizer : DomSanitizer){
}
transform(content){
return this.sanitizer.bypassSecurityTrustHtml(content);
}
}
`
2. Register pipe to app.module.ts
import {EscapeHtmlPipe} from './components/pipes/escape-html.pipe';
declarations: [...,EscapeHtmlPipe]
Use in your template
<div class="demoPipe" [innerHtml]="getDivHtml(obj.header) | keepHtml">
getDivHtml() { //can return html as per requirement}
Please add appropriate implementation for getDivHtml in associated component.ts file.
Just simple use [innerHTML], like below:
<div [innerHTML]="htmlString"></div>
Before you needed to use ng-bind-html...
I would like to use the same HTML template in 3 places, just each time with a different model.
I know I can access the variables from the template, but there names will be different.
Is there a way to pass a model to the ngInclude?
This is what I would like to achieve, of course the attribute add-variable does not work now. Then in my included template, I would acces the detailsObject and its properties.
<pane title="{{projectSummary.ProjectResults.DisplayName}}">
<h2>{{projectSummary.ProjectResults.DisplayName}}</h2>
<ng-include src="'Partials/SummaryDetails.html'" init-variable="{'detailsObject': projectSummary.ProjectResults}"></ng-include>
</pane>
<pane title="Documents" header="true"></pane>
<pane ng-repeat="document in projectSummary.DocumentResults" title="{{document.DisplayName}}">
<h2>{{document.DisplayName}}</h2>
<ng-include src="'Partials/SummaryDetails.html'" add-variable="{'detailsObject': document}"></ng-include>
</pane>
<pane ng-repeat="header in [1]" title="Languages" header="true"></pane>
<pane ng-repeat="language in projectSummary.ResultsByLanguagePairs" title="{{language.DisplayName}}">
<h2>{{document.DisplayName}}</h2>
<ng-include src="'Partials/SummaryDetails.html'" add-variable="{'detailsObject': language}"></ng-include>
</pane>
If I took a bad approach with using ng-include, is there something else I should try?
There is a rather simple solution, although I must admit, it's not what Misko would recommend. But if creating a directive is an overkill for you and getting Brice's patch is not feasible then the following will help you.
<div ng-repeat="name in ['A']" ng-include="'partial.html'"></div>
<div ng-repeat="name in ['B']" ng-include="'partial.html'"></div>
<script type="text/ng-template" id="partial.html">
<div>{{ name }}</div>
</script>
It's quite evident why it works. See an example here: http://jsfiddle.net/Cndc6/4/
NOTE: this is not my original answer but this is how I'd do this after using angular for a bit.
I would create a directive with the html template as the markup passing in the dynamic data to the directive as seen in this fiddle.
Steps/notes for this example:
Define a directive with markup in the templateUrl and attribute(s) used to pass data into the directive (named type in this example).
Use the directive data in the template (named type in this example).
When using the directive in the markup make sure you pass in the data from the controller scope to the directive (<address-form type="billing"></address-form> (where billing is accessing an object on the controller scope).
Note that when defining a directive the name is camel cased but when used in the markup it is lower case dash delimited (ie it's named addressForm in the js but address-form in the html). More info on this can be found in the angular docs here.
Here is the js:
var myApp = angular.module('myApp',[]);
angular.module('myApp').directive('addressForm', function() {
return {
restrict: 'E',
templateUrl: 'partials/addressform.html', // markup for template
scope: {
type: '=' // allows data to be passed into directive from controller scope
}
};
});
angular.module('myApp').controller('MyCtrl', function($scope) {
// sample objects in the controller scope that gets passed to the directive
$scope.billing = { type: 'billing type', value: 'abc' };
$scope.delivery = { type: 'delivery type', value: 'def' };
});
With markup:
<div ng-controller="MyCtrl">
<address-form type="billing"></address-form>
<address-form type="delivery"></address-form>
</div>
ORIGINAL ANSWER (which is completely different than using a directive BTW).
Note: The fiddle from my original answer below doesn't appear to work anymore due to an error (but keeping it here in case it is still useful)
There was a discussion about this on the Google Group you can see it here.
It looks like this functionality is not supported out of the box but you can use Brice's patch as described in this post.
Here is the sample code from his jsfiddle:
<script id="partials/addressform.html" type="text/ng-template">
partial of type {{type}}<br>
</script>
<div ng-controller="MyCtrl">
<ng-include src="'partials/addressform.html'" onInclude="type='billing'"></ng-include>
<ng-include src="'partials/addressform.html'" onLoad="type='delivery'"></ng-include>
</div>
There is a pull to fix this but it looks like it's dead:
https://github.com/angular/angular.js/pull/1227
Without modifying the Angular source code this will solve the problem in a reusable not-too-hacky-feeling way:
directive('newScope', function() {
return {
scope: true,
priority: 450,
};
});
And an example:
<div new-scope ng-init="myVar = 'one instance'" ng-include="'template.html'"></div>
<div new-scope ng-init="myVar = 'another instance'" ng-include="'template.html'"></div>
Here is a Plunker of it in action:
http://plnkr.co/edit/El8bIm8ta97MNRglfl3n
<div new-scope="myVar = 'one instance'" ng-include="'template.html'"></div>
directive('newScope', function () {
return {
scope: true,
priority: 450,
compile: function () {
return {
pre: function (scope, element, attrs) {
scope.$eval(attrs.newScope);
}
};
}
};
});
This is a directive that combines new-scope from John Culviner's answer with code from Angular's ng-init.
For completeness, this is the Angular 1.2 26 ng-init source, you can see the only change in the new-scope directive is the addition of scope: true
{
priority: 450,
compile: function() {
return {
pre: function(scope, element, attrs) {
scope.$eval(attrs.ngInit);
}
};
}
}
Quick'n'dirty solution:
<div ng-init="details=document||language||projectSummary.ProjectResults">
I hear you! ng-include is not that reusable because it has access to the global scope. It's a little weird.
There should be a way to set local variables. Using a new directive instead of ng-include is a cleaner solution.
The ideal usage looks like:
<div ng-include-template="'Partials/SummaryDetails.html'" ng-include-variables="{ 'detailsObject': language }"></div>
The directive is:
.directive(
'ngIncludeTemplate'
() ->
{
templateUrl: (elem, attrs) -> attrs.ngIncludeTemplate
restrict: 'A'
scope: {
'ngIncludeVariables': '&'
}
link: (scope, elem, attrs) ->
vars = scope.ngIncludeVariables()
for key, value of vars
scope[key] = value
}
)
You can see that the directive doesn't use the global scope. Instead, it reads the object from ng-include-variables and add those members to its own local scope.
It's clean and generic.