Angular $sce service seems to be encoding characters and not trusting the html. Is there an option to have the html trusted?
$scope.text = $sce.trustAsHtml('it's broken')
An example.
<p>it's working</p>
<p>{{ text }}</p>
Looks like.
it's working
it's broken
I'd rather not use ng-bind-html because it's meant to be used in a filter like the following.
{{ text | render }}
It is not the $sce that encode your html, actually nothing does that.
But when you use an interpolation {{ text }}, angular will detect that and replace it with a correct value via textNode.nodeValue, not something like innerHTML. Therefore, your ' will be treated as a normal text, not an encoded HTML entity.
That's why the ng-bind-html exists, and nothing prevent you from using the filter inside the ng-bind-html expression.
<div ng-bind-html="text | render | trustAsHtml"></div>
Example filters:
.filter('render', function () {
return function (value) {
return value + '!';
};
})
.filter('trustAsHtml', function ($sce) {
return function (value) {
return $sce.trustAsHtml(value);
};
})
Example Plunker: http://plnkr.co/edit/F8OQvoSzOR06TPepc2Fo?p=preview
Related
i have used angular-translate, and it works great.
But now the problem is how can i use it in my controller functions?
normal we can use it in the html templates as {{ 'mystring' | translate }}
but i actualy want to do this:
function bla(){
var myvalue = 'mystring' | tranlate
return value;
}
and then in my html {{ value }}
As per Docs,to use filter inside controller is as follows.
$filter('filter')(array, expression, comparator)
You need to write something below
app.controller('MainCtr', ['$scope','$translate','$filter', function ($scope,$translate,$filter) {
$translate.use($scope.language.langCode);
$scope.data = $filter('translate')('Title');//where Title is language dependant
});]);
Demo to call filter inside controller
It seems you are trying to show dinamic content on your html. To achieve this you should think in other way to do it using angular-translate. I can guess you are trying to achieve this:
controller.js
$scope.mystring = 'MY_LITERAL_CODE';
inde.html
<span>{{ mystring | translate }}</span>
I have the following filter that seems like it should be working in my view. When added to the directive no data is returned, just as if the data contained a single quote as in "it's".
angular.module('hcApp')
.filter('replace', function(){
return function(text) {
return text.replace(/'/g, '"');
};
});
I'm trying to escape single quotes from my JSON data, which is coming through a CMS. Could it possibly be a conflict with the filters and directive already in place?
<div ng-bind-html="'{{over.contents}}' | to_trusted | replace "></div>
angular.module('hcApp')
.filter('to_trusted', ['$sce', function($sce){
return function(text) {
return $sce.trustAsHtml(text);
};
}]);
You don't need to interpolate the value ('{{over.contents}}'). And you want to_trusted to be the last filter because it wraps the string to tell Angular it's trusted. Try this...
<div ng-bind-html="over.contents | replace | to_trusted "></div>
Also, " is a double quote. For a single quote, use '.
Fiddle
How can I use this json pretty print [ http://jsfiddle.net/KJQ9K/ ] with angularJS?
Lets assume myJsonValue is
{a:1, 'b':'foo', c:[false,'false',null, 'null', {d:{e:1.3e5,f:'1.3e5'}}]}
I want to be able to use below to render pre (as shown in example)
Angular already has the json filter built-in:
<pre>
{{data | json}}
</pre>
The json after the pipe | is an Angular Filter. You can make your own custom filter if you like:
app.filter('prettyJSON', function () {
function prettyPrintJson(json) {
return JSON ? JSON.stringify(json, null, ' ') : 'your browser doesnt support JSON so cant pretty print';
}
return prettyPrintJson;
});
To use your custom prettyJSON filter:
<pre>
{{data | prettyJSON}}
</pre>
ES6 version from #TeChn4K:
app.filter("prettyJSON", () => json => JSON.stringify(json, null, " "))
Another option is to turn the function into a filter...
app.filter('prettify', function () {
function syntaxHighlight(json) {
// ...
}
return syntaxHighlight;
});
HTML...
<pre ng-bind-html="json | prettify"></pre>
JsFiddle: http://jsfiddle.net/KSTe8/
A simpler code:
app.filter('prettyJSON', function () {
return function(json) { return angular.toJson(json, true); }
});
Remember to use the <pre> tag
You have a few options. What I consider the most "AngularJS" way is to wrap your custom object into an Angular service:
myAngularModule.service('myPrettyPrintService', ,myObject );
The inject that into a controller:
myAngularModule.controller('myTestController', function(myPrettyPrintService){}
Then inside the controller, reference the functions and sort:
myPrettyPrintService.syntaxHighlight();
Since anything defined in JavaScript, is global anyway you could technically just access it inside a controller:
syntaxHighlight();
That may screw up with unit testingt because it adds a external, undefined, dependency to your controller.
How can I check if an angular model is an array or an object? Is there a built in or do I have to write a filter isArray with Array.isArray()
{{[] | isArray}} doesn't work
You can use the angular.isArray function. It's built-in inside Angularjs.
If you want to use this function inside your template, you have to create a custom filter: http://docs.angularjs.org/tutorial/step_09
Example of what you want:
angular.module('...', []).filter('isArray', function() {
return function (input) {
return angular.isArray(input);
};
});
Then you can use the filter inside your template:
{{ myVar | isArray }}
I guess you can also add underscore/lodash to the rootScope and use it:
_ = require('lodash')
angular.module('app',[])
.run(function($rootScope){
$rootScope._ = _
})
And in the template:
<div ng-show="$root._.isArray(foo)">
<label> First element of Foo </label>
<span> {{ $root._.first(foo) }} </span>
</div>
The benefits - you have to add lodash only in one place, and it will be available everywhere. You can use many other things the same way, like Math functions for example. Just be reasonable and don't put too much javascript into expressions.
Is there an angular JS command that will do HTML escaping on text? I am processing a custom directive and have need to escape some of the output which it generates.
Internally the AngularJS sanitzer uses a encodeEntities function, but does not expose it. I know I could duplicate the function, but it seems like there should be a standard way of doing this.
Use-Case: I have a custom directive which does language localization. This directive uses a key lookup from a data file to find language text. In some cases this text is allowed to contain HTML, and/or the directive produces HTML to improve the resulting visual formatting. In addition this directive takes Angular expressions as parameters and uses them as replacements for tokens in the strings. I need to encode these parameters as they may not be HTML safe.
The directive is called as an attribute, for example i18n-html='welcome_text_html,1+1,user.name'. The directive then formats the string as described and uses element.html to update the DOM node.
This answer is about escaping, not sanitizing HTML. There are two approaches:
As mentioned by #maniekq, if you can work on the DOM, do:
element.text( scope.myValue );
From this answer, you can use this code from mustache.js and e.g. create an angular filter:
angular.module('myModule').filter('escapeHtml', function () {
var entityMap = {
"&": "&",
"<": "<",
">": ">",
'"': '"',
"'": ''',
"/": '/'
};
return function(str) {
return String(str).replace(/[&<>"'\/]/g, function (s) {
return entityMap[s];
});
}
});
Sanitizing is one thing, but to display all characters and not "execute" HTML code I have used "text" function to set value.
In your directive, to set value, instead of writing:
element.html( scope.myValue );
write:
element.text( scope.myValue );
This answer is derived from #mb21's. The only thing that is changed is utilizing $sce. So you can use this filter in ng-bind-html, without triggering Error: $sce:unsafe.
angular
.module('yourModule', [
'ngSanitize'
])
.filter('escapeHtml', function ($sce) {
// Modified by Rockallite: Add $sce.trustAsHtml() to mute "Error: $sce:unsafe"
// http://stackoverflow.com/a/32835368/2293304
// http://stackoverflow.com/a/28537958/2293304
// https://github.com/janl/mustache.js/blob/master/mustache.js#L82
var entityMap = {
"&": "&",
"<": "<",
">": ">",
'"': '"',
"'": ''',
"/": '/'
};
return function(str) {
return $sce.trustAsHtml(String(str).replace(/[&<>"'\/]/g, function (s) {
return entityMap[s];
}));
}
});
There are two separate issues with escaping HTML. The first issue is that entities need to be encoded, and the second issue is that the result needs to be trusted so the data can be used as html bindings. Adding the following code to your controller(s) provides a solution for both issues using the $sce service.
CoffeeScript Solution:
MyApp.controller('MyController', ['$scope','$sce',($scope,$sce) ->
###
...
###
$scope.html5Entities = (value) ->
value.replace(/[\u00A0-\u9999<>\&\'\"]/gim, (i) ->
'&#' + i.charCodeAt(0) + ';'
)
$scope.trustAsHtml = (value) ->
$sce.trustAsHtml(value)
###
...
###
])
Javascript Solution:
MyApp.controller('MyController', ['$scope','$sce', function($scope,$sce) {
/* ... */
$scope.html5Entities = function(value) {
return value.replace(/[\u00A0-\u9999<>\&\'\"]/gim, function(i) {
return '&#' + i.charCodeAt(0) + ';'
})
};
$scope.trustAsHtml = function(value) {
return $sce.trustAsHtml(value);
};
/* ... */
}]);
The first function html5Entities does the actual entity encoding, while the second function trustAsHtml marks a string as safe to use in Angular for HTML bindings. Both versions require that the $sce service be included in your controller.
Example usage:
<div ng-bind-html="trustAsHtml((html5Entities(product.title) | highlight: $select.search))"></div>
See related issues:
Encode html entities in javascript
AngularJS : Insert HTML into view
You can implement filter like this:
app.filter('escape', escape);
function escape() {
return function (html) {
return angular.element('<pre/>').text(html).html();
};
}
There are two ways to do HTML sanitization in AngularJS. The first is by using the ngBindHtml directive and the second by using the $sanitize service.
function MyCtrl ( $scope, $sanitize ) {
$scope.rawHtml = "<div><script></script></div>";
$scope.sanitizedHmtl = $sanitize( $scope.rawHtml );
}
Then these two are functionally equivalent:
<div ng-bind-html="rawHtml"></div>
<div ng-bind-html-unsafe="sanitizedHtml"></div>
If used in a directive, as in your question, you can simply insert the sanitized HTML:
element.html( scope.sanitizedHtml );
But in most cases when writing directives, you'd have this in a template and use ngBindHtml, as above. But it works for the corner cases.
It's not the straight solution, but if you'd dive into angular-sanitize code, you could find function encodeEntities. It's nice but private. Looking for usages of it you'd go to htmlSanitizeWriter, and then to sanitizeText.
It's still private but used in public filter linky.
Either you can explicitly use linky and hope that no links will be found, or reimplement sanitizeText or encodeEntities int your services.
Use [innerHtml] shorthand tag in a HTML template file you are using in your Angular app.
My example shown below to escape HTML generated by wordpress on post_content that is retrieved from my WP API and therefore the html tags will not display in the browser:
<div [innerHtml]="post.post_content" *ngIf="post && post.post_content"></div>
Hope this helps.
You can use encodeEntities() function in ngSanitize to escape & < > etc.