When to use double braces {{}} in angularJS - angularjs

Taken from the Angular documentation:
Angular Expressions
Angular expressions are JavaScript-like code snippets that are mainly
placed in interpolation bindings such as
<span title="{{ attrBinding }}">{{ textBinding }}</span>
but also used directly in directive
attributes such as ng-click="functionExpression()".
For example, these are valid expressions in Angular:
1+2 a+b user.name items[index]
However I'm a little confused as to when to use the double braces syntax {{}} and when not to. The documentation seems to suggest that you don't need them when using expressions within the directive attributes (see the ng-click example above).
Although the following code which works offers anecdotal evidence to the contrary:
<ul id="Menu">
<li ng-repeat="appModule in applicationModules"
id="{{appModule.Name}}"
ng-class="{ 'selected' : selectedAppModule == '{{appModule.Name}}' }"
ng-click="menuClicked(appModule.Name)">
{{appModule.Display}}
</li>
</ul>
Note how in the ng-class directive the double braces are used and inside the ng-click directive they are not.
How do you know when to use them and when not to?

It depends on the directive attribute in question and the type of binding it uses. Further more it depends on what you intend in the given situation.
From your example:
ng-repeat="appModule in applicationModules"
No need for the braces as this expression is evaluated by angular inside the ng-repeat directive.
id="{{appModule.Name}}"
Here we need braces as we want the id to be equal to the value of the expression.
ng-class="{ 'selected' : selectedAppModule == '{{appModule.Name}}' }"
I'm pretty sure this can be written as:
ng-class="{ 'selected' : selectedAppModule == appModule.Name }"
And you get the same behaviour.
ng-click="menuClicked(appModule.Name)"
In this example we need the ng-click to be bound to the method named menuClicked.
Generally we use {{}} when we want to evaluate the expression and when dealing with attributes we don't always need to use {{}} as they are in many cases evaluated behind the scenes.
Simple Tip A rule of thumb for when {{}} is needed is by thinking of it as a wrapper for a .ToString()-method. Does converting the expression to a string make sense, then so does using {{}}. (Any counter examples are very welcome)

Check the documentation. Avoid using using interpolation {{ }} when
the documentation says that the directive takes an expression, . In the case of ng-src, the documentaion explicitly says use {{ }}. If the attribute is not an AngularJS directive, use interpolation.
Erroneous
ng-class="{ 'selected' : selectedAppModule == '{{appModule.Name}}' }"
The above example is an example of mixing interpolation and Angular epressions.
Instead use:
ng-class="{ 'selected' : selectedAppModule == appModule.Name }"
From the Docs:
Why mixing interpolation and expressions is bad practice:
It increases the complexity of the markup
There is no guarantee that it works for every directive, because interpolation itself is a directive. If another directive accesses attribute data before interpolation has run, it will get the raw interpolation markup and not data.
It impacts performance, as interpolation adds another watcher to the scope.
Since this is not recommended usage, we do not test for this, and changes to AngularJS core may break your code.
— AngularJS Developer Guide - mixing interpolation and expressions
Update
Don't use interpolation with:
ng-selected, see AngularJS ng-selected Directive API Reference
ng-disabled, see AngularJS ng-disabled Directive API Reference
ng-required
ng-if
ng-show
ng-hide
ng-open
ng-value
ng-repeat
ng-options

Related

ng-messages dynamic form name [duplicate]

From the Docs:
Embedding interpolation markup inside expressions
Note: AngularJS directive attributes take either expressions or interpolation markup with embedded expressions. It is considered bad practice to embed interpolation markup inside an expression:
— AngularJS Developer Guide - Interpolation
I am looking for a well written canonical answer to which I can point readers.
From the Docs:
Why mixing interpolation and expressions is bad practice:
It increases the complexity of the markup
There is no guarantee that it works for every directive, because interpolation itself is a directive. If another directive accesses attribute data before interpolation has run, it will get the raw interpolation markup and not data.
It impacts performance, as interpolation adds another watcher to the scope.
AngularJS Developer Guide - Interpolation
Directives which expect Boolean values won't work:
ERRONEOUS
<input type="checkbox" ng-hide ="{{x.thenumber === null}}" />
When the expression evaluates to the Boolean value false, interpolation will return the string "false". Strings that have length greater than zero are truthy. The ng-hide directive will always hide and never show the input element.
CORRECT
<input type="checkbox" ng-hide="x.thenumber === null" />

"ng-switch on" and "ng-switch" difference

I was studiously reading the AngularJS API reference for the ngSwitch directive when I came to that part :
place an expression on the on="..." attribute (or the ng-switch="..."
attribute)
So of course I was wondering why there are two ways to place the expression since both of them seems to work the same way.
<div ng-switch="expression">
<div ng-switch on="expression">
I assume there is a reason but I do not find anything for now.
Plunker to test : http://plnkr.co/edit/VAq1t4744bnNC6RgZtEn?p=preview
There is no difference.
You can check the sources of ng-switch directive
https://github.com/angular/angular.js/blob/master/src/ng/directive/ngSwitch.js
var watchExpr = attr.ngSwitch || attr.on

ng-show and ng-model can't work together on the same $scope variable

I am trying to have a span element show some $scope variable only if it is not null or empty.
I know i can accomplish this with only ng-model, but i don't understand they this won't work:
<span ng-show="x !== null" ng-model="x"></span>
or something similar to this.
ng-model is for two-way binding (as #MK Safi said above), which means its for elements that both display values and allow users to change those values. Probably not a <span/>...
If you're just looking to show the value of the model in the span, use ng-bind or expression syntax - {{ x }}
This way, ng-show should work properly to add the relevant CSS styles as x changes.
E.g.:
<span ng-bind="x" ng-show="x !== null"></span>
or
<span ng-show="x !== null">{{ x }}</span>
ng-model is used mostly for input, textarea, and select elements. It's not used on span, div, or p elements, etc.
From Angular documentation on ngModel
The ngModel directive binds an input,select, textarea (or custom form control) to a property on the scope using NgModelController, which is created and exposed by this directive.
Yes, as MK Safi says ng-model is only used to bind inupts to $scope variables. This should work though:
<span ng-show="x !== null">{{ x }}</span>
Just use the templating engine to display the value in $scope.x

Difference between ng-bind and interpolation {{}} in Angular [duplicate]

This question already has answers here:
AngularJS : Why ng-bind is better than {{}} in angular?
(12 answers)
Closed 1 year ago.
Is there any difference between
{{ }} and ng-bind in angular.
I am quite new to Angular. I started with using {{ }} and then in the documentation i find ng-bind. I think they do the same work but then why an extra directive, if not then please tell the difference.
There is some hint in the official docs: https://docs.angularjs.org/api/ng/directive/ngBind
Typically, you don't use ngBind directly, but instead you use the
double curly markup like {{ expression }} which is similar but less
verbose.
It is preferable to use ngBind instead of {{ expression }} if a
template is momentarily displayed by the browser in its raw state
before Angular compiles it. Since ngBind is an element attribute, it
makes the bindings invisible to the user while the page is loading.
The most obvious difference between them is Flash of Unstyled content while using {{ ... }}.
However, there is a more subtle difference between the two if the object you pass to {{ obj }} and ng-bind="obj" is not a string.
From https://stackoverflow.com/a/19744728/987185 :
Depending on whether you use {{ ... }} or ng-bind syntax, the
.toJSON and the .toString function on your object will be called
to determine its representation.
In addition to the above mentioned answers,
Performance Issues with Interpolation:
As explained in this thread better,
ng-bind is a directive and will place a watcher on the passed variable. So the ng-bind will only apply when the passed value does actually change.
The brackets on the other hand will be dirty checked and refreshed in every $digest, even if it's not necessary.
{{ }} can flash when the page is loading, ng-bind hides the expression properly until it is displayed correctly.
In AngularJs ng-bind directive works as alternative to the interpolation directive {{ }}. By inserting an ng-bind attribute to HTML element we can insert AngularJS data into it.
Here is an example:
<div ng-controller="DemoController" >
<span ng-bind="demoData.doThis()"></span>
</div>
The Key Difference is ng-bind attribute wont show Html content on page loading, where as interpolation Directive show as flash of content without style while page loading.
Another difference is the way ng-bind and interpolation display the data.
ng-bind calls the toString() method, whereas interpolation uses a custom "stringify" function.
Example
<div ng-controller="showClockCtrl">
<p>The current time is {{currentDateTime}}.</p>
<p>The current time is <span ng-bind="currentDateTime"></span>.</p>
</div>
<div ng-controller="showClockCtrl">
<p>MyObject is {{myObject}}</p>
<p>MyObject is <span ng-bind="myObject"></span></p>
</div>
<script>
var showClockCtrl = function ($scope) {
$scope.currentDateTime = new Date();
$scope.myObject = {
'key1': 'value1',
'key2': 'value2',
'key3': 'value3'
}
};
</script>
Output
The current time is "2017-11-18T15:09:59.429Z".
The current time is Sat Nov 18 2017 10:09:59 GMT-0500 (EST).
MyObject is {"key1":"value1","key2":"value2","key3":"value3"}
MyObject is [object Object]
Sometimes when we load our application in the browser , we can notice flashing content for some milliseconds before {{ name }} is resolved and data is loaded.
This happens because the template is loaded before AngularJS had a chance to go in and compile the elements. To resolve this issue, you can use ng-cloak directive.
In the first approach(i.e. {{}}), AngularJS evaluates the expression then replaces it with some value which sometime be left with the flashing double curly brackets but ng-bind saves this time by informing AngularJS to put the contents of the expression within the element itself.
Note:
{{}} sometimes cause performance issue if we have thousand of bindings in our page.In these scenario's, we should go with ng-bind.
Interpolation is only used for a Read-only purpose and you cannot assign a value to inside the mustache bracket to a variable that has been declared inside the Typescript file.
The basic difference between them is that ng-bind should always be used inside the element <> but Interpolation directive can be used inside, outside and between the elements.
Not an answer, but ng-bind is easily exchangable by ng-bind-html, which puts actual html text inside the element instead of pure text.
Since I was wondering for (ok, just) minutes, I add it here as well. My problem was, text-DOM explorer shows the same output.

ng-class doesnot get evaluated

<div ng-if="question.type =='options'" ng-repeat="option in question.options" >
<ion-radio name="{{$parent.question.id}}"
ng-model="$parent.question.answer"
required ng-value="option.id"
ng-class="{'has-custom-error':submitted && questionForm.{{$parent.question.id}}.$invalid,
'has-custom-success':questionForm.{{$parent.question.id}}.$valid }"
>
{{option.text}}
</ion-radio>
</div>
I have to add has-custom-error on user submitting the form without selecting the option.That is form is not valid but the ng-classis not getting evaluated.
The demo code is over here:http://plnkr.co/edit/FwjoCTYONvi3BoFHNKFK?p=preview
I don't think it is possible to use {{ }} expressions on a ng-class expression. You should be able to use it like this questionForm[$parent.question.id]
Also I never got ng-class working with classes with - between the parts, only CamelCase like hasCustomError. So {hasCustomError: questionForm.$invalid} should work.
Have you considered using the styleClass ng-invalid-required that is already used by angular for your styling? It is usually a lot cleaner, since there is no need for all the ng-class expressions
There is at least one problem with your code. You must not use interpolation {{}} within your ng-class attribute. Here is the correct syntax:
ng-class="{'has-custom-error':submitted && questionForm[$parent.question.id].$invalid, 'has-custom-success':questionForm[$parent.question.id].$valid }"
When you are inside an Angular expression, you don't need the mustache braces. So your code should be:
<div ng-if="question.type =='options'" ng-repeat="option in question.options">
<ion-radio name="{{$parent.question.id}}"
ng-model="$parent.question.answer"
required ng-value="option.id"
ng-class="{'has-custom-error':submitted && questionForm[$parent.question.id].$invalid,
'has-custom-success':questionForm[$parent.question.id].$valid }">
{{option.text}}
</ion-radio>
</div>
The variable form a.b has been replaced by the indexer form a["b"] so that it is evaluated correctly.
You can't use double-mustached expressions ({{ ... }}) inside expressions. The ng-class value is already an expression of type object, so you're supposed to use JavaScript syntax inside this attribute:
ng-class="{'has-custom-error': submitted && questionForm[$parent.question.id].$invalid,
'has-custom-success': questionForm[$parent.question.id].$valid }"
The use of $parent is also unecessary. BTW, you're not using it for your ng-repeat expression:
ng-repeat="option in question.options"
So you should simply use question instead of $parent.question: the scope of the ng-repeat block inherits from its parent scope, and the question is thus available through inheritance.
Note that, playing with your plunkr, it seems like the ion-radio directive that you're using doesn't correctly set the name attribute of the input it generates. This is probably why the CSS classes don't appear.
ng-form is the solution to my problem.But the problem that I am facing is in the name attribute of my ion-radio directive. For radio hence i used angular ng-invalid-required.And for other html tag i used ng-form.$invalid

Resources