Is there a way to tell angular and angular-translate to handle strings which contains HTML content.
I have add_card-title = "To make ordering even quicker, <span class="nowrap">add a card now</span>" as my Lang string. When i use it in my template by writing <p>{{'add_card-title' | translate}}</p> I get string as it is.
Output: To make ordering even quicker, <span class="nowrap">add a card now</span>
expected output: To make ordering even quicker, add a card now
I know i can use ng-html-bind-unsafe but it is not helping.
Not working:
<p ng-html-bind-unsafe="{{'add_card-title' | translate}}"></p>
Is there any way to achieve it?
Here is my plunker: http://plnkr.co/edit/nTmMFm9B94BmbTgo2h8H?p=preview
For reference you can see this issue: https://github.com/PascalPrecht/angular-translate/issues/173
note: i do not want to invlove controller to handle it.
You can do this out of box with angular-translate 2.0 these days.
<p translate="{{ 'PASSED_AS_INTERPOLATION' }}"></p>
works wonders for me.
You have to use the ng-bind-html directive without curly braces ({{ }})
To know the configuration needed in order to use that directive (ngBindHtml), follow this link: https://docs.angularjs.org/api/ng/directive/ngBindHtml
After ngSanitize is included, the following code should work:
<p ng-bind-html="'add_card-title' | translate"></p>
This works for me... the HTML is interpreted for nice styling (e.g. bold, italics, etc.)
<p translate="translationId"></p>
However, I also needed to ensure that I wasn't using escape strategy in the provider setup. That messed me up for a while.
Works: $translateProvider.useSanitizeValueStrategy( 'sanitize' );
Nope: $translateProvider.useSanitizeValueStrategy( 'escape' );
https://angular-translate.github.io/docs/#/guide/19_security
Using: angular-translate v2.13.1
You can use <p [innerHTML]="'add_card-title' | translate"></p>
I have found the solution.
I was using AngularJS v1.2.0-rc.3 which has got ng-html-bind-unsafe deprecated. Now angular has ng-bind-html instead of ng-html-bind-unsafe. But one has to inject angular-sanitize as a dependency to get it working.
I replaced
<p ng-html-bind-unsafe="{{'add_card-title' | translate}}"></p>
with
<p ng-bind-html="'{{'add_card-title' | translate}}'"></p>
and things started working.
By default AngularJS escape and code it displays for safety reasons, you need to tell angular of the strings you don't want to escape, in older times before AngularJS 1.2 developers could do that by using ng-bind-html-unsafe but in AngularJS 1.2 that has been deprecated.
To use html tags in strings, in AngularJS 1.2+, you need to download angular-sanitize module and include it in your application dependencies.
Any string contains html code you can display it by using ng-bind-html Automatically uses $sanitize, in your case it will be ng-bind-html="'add_card-title' | translate"
For reference:
On Medium
AngularJS Documentation
Here are many ways to mix up html (along with scope variables, along with interpretion if you need things like ng-click in your html translations):
http://plnkr.co/edit/OnR9oA?p=preview
<div>{{'TESTING1_SIMPLE_VAR_REPLACE' | translate: '{name: "John Smith", username: "john.smith12"}'}}</div>
<div translate='TESTING1_SIMPLE_VAR_REPLACE' translate-values='{ name: "Jake Smith", username: "jake-smith-101" }'></div>
<div translate="TESTING1_SIMPLE_VAR_REPLACE_NA" translate-value-name="{{name}}" translate-value-username="{{username}}" translate-default="Hello {{name}} ({{username}})"></div>
<br/><br/>
<div>{{'TESTING1_SIMPLEHTML' | translate}}</div><!-- doesn't compile the html -->
<div translate="TESTING1_SIMPLEHTML" translate-default='DEFAULT(not used since there is a translation): This <b>translation</b> has a link.'></div><!-- this and below compile the html -->
<div translate="TESTING1_SIMPLEHTML_NA" translate-default="DEFAULT(used since translation not available): This <b>translation</b> has a <a href='http://google.com' target='_blank'>link</a>."></div>
Uses ng-bind-html and sanitize: <div ng-bind-html="'TESTING1_SIMPLEHTML' | translate"></div>
<br/><br/>
<div translate="TESTING2_SCOPE" translate-values="{timer: timer}" translate-default="DEFAULT(not used since there is a translation): Seconds: <a href='http://google.com' target='_blank'>{{timer}} seconds</a>."></div>
<div translate="TESTING2_SCOPE" translate-value-timer="{{timer}}"></div>
<div translate="TESTING2_SCOPE_NA" translate-default="DEFAULT(used since translation not available): Seconds: <a href='http://google.com' target='_blank'>{{timer}} seconds</a>."></div>
<br/><br/>
<div compile-unsafe="'TESTING3_COMPILE' | translate"></div><!-- old way to do before angular 2.0-->
<div translate="TESTING3_COMPILE" translate-compile></div>
<div translate="{{'TESTING3_COMPILE_SCOPE'}}" translate-compile translate-value-name="{{name}}" translate-value-username="{{username}}" ></div> <!-- not sure of advantage of this style, but saw an example of it -->
<div translate="TESTING3_COMPILE_SCOPE" translate-compile translate-value-name="{{name}}" translate-value-username="{{username}}" ></div>
<div translate="TESTING3_COMPILE_SCOPE" translate-compile translate-values='{ name: "Jake Smith", username: "jake-smith-101" }' ></div>
"lng_pageFooter" : "Copyright © • 2018 • My Company • Powered by My Company™"
...
$translateProvider.useSanitizeValueStrategy('escape');
....
app.filter('trusted', ['$sce', function($sce) {
var div = document.createElement('div');
return function(text) {
div.innerHTML = text;
return $sce.trustAsHtml(div.textContent);
};
}])
....
<span ng-bind-html="'lng_pageFooter' | translate | trusted"></span>
I tried both your answers and none of them worked on 1.0.7 so for everyone that's working pre 1.2 you can do it like this
<p ng-html-bind-unsafe="'add_card_title' | translate"></p>
Simply use innerHtml. Eg <p [innerHtml]="'lorem.ipsum' | translate"></p>
Related
I am trying to connect some different html code to my view with ng-bind-html.
I already added ngSanitize
Firstly I am using ng-for by ui-select-choices
<ui-select-choices repeat="test in dataTest>
. and I want to bind test.name with some Html
<small> ( {{ TEST_BTN | translate }}) </small>
The Test_BTN is being used for Translation purpose there fore I can't leave it out from code.
when I try to use them all in ng-bind-html nothing will be shown
when I try to use them all in ng-bind the html code will be shown.
when I try to use ng-bind andng-bind-html seperetly , ng-bind-html html won't be shown.
How am I suppose to fix this?
EDIT : I am trying to show the result in a new div with ng-if
something like : <div data-ng-if="test.isSomething" ng-bind="test.name" ng-bind-html="' <small>({{'BTN_ADD' | translate}})</small>'" ></div> (Which doesnt show the ng-bind-html part )
EDIT 2 :
I deleted the {{ }} from data-ng-bind-html and used the translation explicitly with the $translate service in my controller.
And It worked.
You can't use ng-bind and ng-bind-html on the same element, and you can't use {{}} in either one of them. It's not necessary to concatenate the <small> tag inside the ng-bind-html, it should be in the template itself. And you have some syntax error nested-quotes issues in your ng-bind-html clause.
It's not clear to me from your description which of test.name, TEST_BTN or BTN_ADD you actually intend to use; I'm going to assume you really want test.name here but if one of those other variables contains the HTML you're trying to embed, just substitute its name in place of test.name:
<div ng-if="test.isSomething">
<small ng-bind-html="test.name | translate"></small>
</div>
I'm reading the book ng-book on angular 2 and there is the following:
let loadingGif: string = ((<any>window).__karma__) ? '' : require('images/loading.gif');
#Component({
selector: 'youtube-search',
template: `
<div class='container'>
<div class="page-header">
<h1>YouTube Search
<img
style="float: right;"
*ngIf="loading"
src='${loadingGif}' />
</h1>
</div>
I'm interested in this part:
src='${loadingGif}'
The short note in the book says the following:
Notice that our img has a src of ${loadingGif} - that loadingGif
variable came from a require statement earlier in the program. Here
we’re taking advantage of webpack’s image loading feature. If you want
to learn more about how this works, take a look at the webpack config
in the sample code for this chapter or checkout
image-webpack-loader⁴².
But there are no details. Can somebody please how does it all work?
This only works with inline templates (template in *.ts file) but not when the template is in an *.html file (like templateUrl: './my.component.html).
src='${loadingGif}'
Is TypeScript string interpolation and not related to Angular. It replaces ${loadingGif} with the content of loadingGif
In my app I try to concat two strings: email and some text.
But I have a trouble, I need text part translateable "on the fly" so I wrote:
$scope.textUnsubscribe = 'SUCESSFULL_UNSUBSCRIBE';
in view:
<h4 ng-bind-html="textUnsubscribe | translate"></h4>
sure I can do (email + text):
<h4 ng-bind-html="userEmail"></h4>
<h4 ng-bind-html="textUnsubscribe | translate"></h4>
but then I have style bug...
Can I somehow put into one ng-bind-html two scope variables? one is "static" and second is translateable?
like:
<h4 ng-bind-html="userEmail, (textUnsubscribe | translate)"></h4>
If it's only simple string like email. You don't need ng-bind-html, ng-bind will be enough. Adding -html make ng-bind less safer. Anyway ng-bind can be used multiple times. If you have a "style bug" with it, it comes from your HTML (you have multiple h4).
Anyway, you can do it on a simple ng-bind like this :
<h4 ng-bind="userEmail +' '+ (textUnsubscribe | translate)"></h4>
I am currently trying to add links in my view. I do have links which basically contains html tags as strings.
I tried:
<p data-ng-repeat='i in links' >{$ i.link $}</p>
which basically just deploy in my view : mylink
So I did try:
<p data-ng-repeat='i in links' ><span data-ng-bind-html="i.link"></span></p>
It doesn't work though, any idea how could I achieve this ?
Thanks.
Add the $sce as a dependancy of the module
angular.module('myApp', ['$sce']);
When getting the links
angular.forEach($scope.links, function(value){
value.link = $sce.trustAsHtml(value.link);
});
Using Safe Contextual Escaping (docs.angularjs.org/api/ng/service/$sce) and using trustAs delegate you're telling Angular that this value is safe to use within that context. In this example. $sce.trustAsHtml returns an object that angular can trust is safe to as HTML.
In the first case, you'll actually want to use:
<p data-ng-repeat='i in links' >{{ i.link }}</p>
Double braces, not brace-dollar. In the second case, ng-bind-html will require that you have added "ngSanitize" to your module's dependency list.
angular.module('yourAppNameHere', ['ngSanitize'])
Edit:
If you really do want clickable links on the page, then do pretty much what #sreeramu suggested (Though I'd see if you can't find a way to add a nice description):
<p data-ng-repeat='i in links' ><a ng-href="{{i.link}}">{{i.desc}}</a></p>
(Notice that he suggested using ng-href, instead of href. He's right.)
Insert ngSanitize as a dependency to you app:
angular.module('myApp', ['ngSanitize'])
But before be ensure that you are including the script angular-sanitize.js.
Good luck!
It might be that your links have already got the a tags with it so in this case you do not need to re-add the a tags...
In this case do this...
Add this to you scripts (include acc. to your angular version)
<script type="text/javascript"
src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular-
sanitize.min.js"></script>
Add this to your app.js
var app = angular.module('modulename', [ 'ngSanitize']);
And than in your view do this
If it is the div that you want the link to attach to...
<div ng-bind-html="i.link"></div>
The above would give you something as this
<div><a href='your link'></a></div>
In my controller I assign:
$scope.currentThing.data
And in my template sometimes I need
currentThing.data.response[0].hello
and sometimes
currentThing.data.otherStuff[0].goodbye
//or
currentThing.data.anotherThing[0].goodMorning
So I was wondering if it is possible to create a shortcut for this variables straight in the templates, something like:
{{response = currentThing.data.response[0]}}
So that I can use it like this {{response.hello}}.
In general, is it possible to assign temporary variables from the template? I don't need to have any data-binding, I would need them only for generating the template and then they can disappear forever
You can do that in controller like here: http://jsbin.com/moyuhe/1/edit
app.controller('firstCtrl', function($scope){
$scope.currentThing = {
data: [
{response:[
{hello:1},
{hello:2}
]}
]
};
$scope.temp = $scope.currentThing.data[0];
});
HTML:
<div ng-controller="firstCtrl">
{{temp.response |json }}
</div>
You might be able to use ngInit: https://docs.angularjs.org/api/ng/directive/ngInit
Although it seems that using it outside of ngRepeat is frowned upon.
<div ng-init="myvar = currentThing.data.response[0]">
<span>{{myvar.hello}}</span>
</div>
I haven't tested it like this but that's the closest thing I can think of that may solve your problem.
Yes, it is possible using syntax like
{{ variable = ( expression ) }}
anywhere in HTML template (not just ng-init as some suggest).
It is exceptionally useful in cases when you need to use a calculated variable more times - it does not need to be calculated each time.
Some example
<!-- can use it before -->
<p> Calculated value is {{calculated}} </p>
<div ng-repeat=" item in calculated = ( allItems | filter1 | filter2 | filter3 ) ">
{{item}}
</div>
<!-- can use it after-->
<p> Calculated value is still {{calculated}} </p>
Edit: so in your case
{{response = ( currentThing.data.response[0] ) }}