angular-translate: unable to use dynamic data in nested directives - angularjs

I'm using angular-translate package. It provides developers with different things. One thing is internal interpolation so you are able to use dynamic data inside translation strings. Or even angular directives.
Assume we have greeting.
'Hello {{name}}!'
That is used in template like that:
<h3 translate="greeting" translate-values="vm.user" translate-compile></h3>
But user.name maybe empty. In this case I'd like to see "Hello anonymous!". I'm trying to use ng-if but it does not work in expected way:
'greeting': 'Hello <span ng-if="!name">anonymous</span>{{name}}!'
It will output "Hello anonymousJack!" like if name is empty and is not empty at the same time.
Why I don't want to inject ng-if into template instead of translation? Because depending on language there will be different position of name part. So I'd like to avoid unclear decomposition like
<span translate="greeting_1"></span>
<span ng-if="vm.user.name" bind="vm.user.name"></span>
<span ng-if="!vm.user.name" translate="greeting_anomymous"></span>
<span translate="greeting_2"></span>
This looks unclear and confusing. Especially in more complex cases.

I've found all data passed through translate-values is available in nested variable interpolateParams. So next will work:
'greeting': 'Hello <span ng-if="!interpolateParams.name">anonymous</span>{{name}}!'

Related

Using directives as part of angular-translate's translate-values, how to compile?

I am in the process of internationalizing a website and have come across a sticking point with angular-translate.
Suppose I have a translationProvider for english supplying the following text:
"example.message": "I need a {{link}} or {{customDirectiveOutput}} to render directives in me"
"link.text": "this link"
I am now trying to get some HTML into those two placeholders by doing something like the following:
<div translate="example.message"
translate-values="{
link: '<a ui-sref=\'stateName\'>{{ \'link.text\' | translate }}</a>'
customDirectiveOutput: '<span my-custom-directive=\'vm.object\'></span>'
}">
</div>
Where ui-sref is from the ui-router and adds an attribute like href="/path/to/my/state", and my-custom-directive places inner html inside the span sort of like this:
<span my-custom-directive='vm.object'>
<span class='foo'>{{vm.object.foo}}</span>
<span class="bar">{{vm.object.bar}}</span>
</span>
The link tag I can "cheat" around by just hard-coding the href onto the a tag and that isn't so bad to duplicate the /path/to/state, though I'd prefer not to.
The custom directive, however, is conditional on its output so I can't just cheat the output into the translate-values
I've tried doing something in the controller for the page like
$scope.value = vm.getValue();
var element = $compile('<span my-custom-directive="value"></span>')($scope);
return element[0].outerHTML;
But this unfortunately creates an infinite digest loop. I feel like this is the right "path", having some JS pre-compile the fragment I need to insert into the translation, but I'm stuck as to how to accomplish that!
How can I insert angular-compiled HTML with directives attached into a translated string?

when should I write code with `{{}}` and without `{{}}` in html of angular js project

May be This is a simple question but it is challenging for me.
In angularJS when i write {{}} in html code so i write code like this like
if i talk about dynamic id, we write like code this
<div ng-repeat = 'item in itmes track by $index'>
<div id = "div-{{$index}}">{{item.name}}</div>
</div>
If i use any model without {{}} i write this example
<input id = 'name' ng-model = "item.name"/>
whenever i am coding in angular js, i write code without {{}} then if it is not work then i try code with {{}} and vise versa. and randomly 1 will correct
Question is when i write code with {{}} and without {{}} in html code ?
After the OP explained what exactly was the problem.
So, the question here is very simple: when do we use {{}} and when we don't in the context of ng-model.
When you do a <input type=... ng-model="someModel>, what you're essentially telling Angular is: "Here is an input element; attach $scope's someModel variable to the value of this input element.
Now, you can use this in your JavaScript controller like so: $scope.someModel, but what about HTML? We have a templating language in Angular, and when you give it some variable (say someModel), it'll search its $scope for it, and then put in the value there. If it is unable to, it'll throw a nasty error.
In essence, {{}} GETS the value, without that, you generally set the variable to gold the value of something.
Very simply put, AngularJS thinks that the content within the brace is an expression, which must be resolved. Once it is, Angular puts the value of the resolved expression there. In the most basic of the terms, you just tell it: "Here is some expression; put the evaluated value instead."
In ES6, we call it template strings.
So, you'll use it for expressions which mutate after every iteration. Say, a loop or something. Places where you know what the answer is, or you have static content, you won't use it.
Say you have the following bit of code:
...
...
$scope.figureOne = 10;
in your controller.js and the following in its view file:
<div>My age is {{ figureOne }}</div>
Angular gets the value from the $scope, and puts it there; so, the rendered form will be: My age is 10. However, if you had the following
<div>My age is figureOne</div>
This time, Angular knows that there is nothing to evaluate or resolve, so, it'll just render it as it is: My age is figureOne.
I hope I made it clear! :)
Angular directives have different types of parameters. Some parameters (#) expect string values and some expect javascript expressions (=) (with variables bound to $scope).
There's no obvious way to know which parameter expects what type of value (aside from looking at documentation).
If a variable expects static string value and you have an angular expression
then you'll need to evaluate it by wrapping in {{}}
If there variable expects an expression and you have an expression
simply type that in.
It's the best to avoid using {{}} where possible, your dynamic ID will fail when Angular hasn't interpolated the expression yet, use ng-attr-id="div-{{$index}} for that. https://docs.angularjs.org/guide/directive#-ngattr-attribute-bindings
Another example, if you have a slow connection and Angular isn't loaded yet users will see the {{}}, you can avoid this by using ng-bind="".
See this thread for more info: AngularJS : Why ng-bind is better than {{}} in angular?
It is very simple.
{{something}} - used for one way binding(Static).
<input type="text" value="{{something}}">
Now if you change its value in HTML ,you can not get it by $scope.something in js.
but If you use ng-model="something",you can get its value in JS.
This happens because ng-model is two way binding.
<input type="text" ng-model="something">
Mostly We use ng-model for forms and {{}} to display static information like User details or else.

AngularJS: Is there a convenient way to show and bind on an element if value is defined?

I am looking for one line syntax for this:
<span ng-if="value">{{value}}</span>
Maybe something like:
<span ng-bind-if="value"></span>
If saving characters is important I would recommend creating a custom directive and handle the logic internally.
<span my-hide-if-undefined="value"></span>

Don't evaluate variable in view

I have a site built with AngularJS. I need to put a text somewhere on the page that looks something like this: Use {{name}} to display the username.
But AngularJS automatically tries to evaluate {{name}}. But in this case I don't want it to be evaluated. I just simply want to show that as a text.
I already tried to use the unicode characters: {{name}}. But it still evaluates that...
Is there a way to do this?
Use the ngNonBindable directive
<span ng-non-bindable>Use {{name}} to display the username.</span>

Custom Angularjs directive vs. ng-class

Several times when creating or customizing a directive (either my own directive or for example https://github.com/dpiccone/ng-pageslide) I get a point where all the display logic is controlled by a single css class. At that point the directive boils down to adding and removing a single class. So instead of using a new directive I can simply use the ng-class directive (see an example here: https://gist.github.com/Hypercubed/8f40556eb0f6eddbcca3). Is there an advantage to the custom directive approach vs the ng-class/CSS styles approach? I guess the custom directive doesn't depend on $animate? Am I just doing it wrong?
Sorry for another directive vs. XXX question.
I think you're failing to see the forest for the all tress. You're focusing on a very minute detail and missing the larger picture. Directives are more than simply applying styles. I think an example is best. For example, take the rating directive. If you wanted to render a star rating model it might look like this:
<div ng-rating="album.rating" max="5"></div>
That may add the following to the DOM:
<ul class="inline">
<li ng-repeat="i in max">
<i ng-class="{ 'icon-start-empty': i > rating, 'icon-star': i <= rating }"></i>
</li>
</ul>
Under the covers ng-class it utilized, but that is only a part of the logic encapsulated in the rating directive. It allows the user to configure how many stars the rating is out of, and renders the same number of li elements. Then because you wrote a directive it allows you to reuse this logic where ever it's required. Using ng-class only works in that 1 location. If you want to do the same thing you're copying code which is a sign maybe you want to wrap that logic up in a directive.

Resources