Why the ngStyle directive is declared into the []? - javascript

I am an absolute beginner with Angular 2 and I have the following dount related the correct syntax of the ngStyle directive.
I have this example (that works fine):
<p [ngStyle]="{backgroundColor: getColor()}">Server with ID {{ serverID }} is {{ getServerStatus() }}</p>
I know that, in this case, the ngStyle directive is adding something like to:
style="background-color: green;"
at my HTML paragraph.
My doubt is related the correct meaning of this syntax. Why is it:
[ngStyle]="{backgroundColor: getColor()}"
and not
ngStyle="{backgroundColor: getColor()}"
Why is it into the [...]? What it exactly means?

It's called property binding. With the brackets the compiler tries to evaluate the expression. Without it, you are just passing a string.
So with the brackets, you are passing a javascript object:
{
backgroundColor: getColor()
}
Whereby the compiler will call the getColor() method from the component to get the right color.
On the other hand, and going off topic here, but if you want to pass a string while using brackets, you should wrap them in single quotes:
<div [property]="'hiii'"></div>

Angular 2 has 3 types of directives:
Attribute directives.
Structural directives.
Components.
ngStyle is an attribute directive. And all attribute directive to which we need to pass/assign values are written inside square brackets.
The built-in NgStyle directive in the Template Syntax guide, for example, can change several element styles at the same time.

Related

Angular directives with and without []?

I'm reviewing this tutorial which uses a tooltip directive like this:
CASE A: No surrounding []
<p tooltip="Tooltip from text">Tooltip from text</p>
CASE B: Surrounding []
<p [tooltip]="template">Tooltip from TemplateRef</p>
I just want to make sure I understand this correctly.
If we use the tooltip directive without brackets, then the text string gets passed to the directive (Tooltip from text").
When we surround the tooltip with brackets, then the template property, which should be available on the component view (The view using the directive), gets passed in?
If we use the tooltip directive without brackets, then the text string gets passed to the directive
Yes Exactly.
For the second case, [tooltip]="template"
[prop] is for object binding to properties (#Input() of an Angular component or directive or a property of a DOM element) of the angular Component.

Angular: When to put a variable inside curly braces? [duplicate]

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

Angular repeat directive syntax

I am brand new to AngularJS and while doing the Codecademy course I got stuck. I was trying to repeat a directive using the following syntax.
<div class="card" ng-repeat="app in apps">
<app-info info="{{ app }}"></app-info>
</div>
I played around a bit and figured out I needed to remove the curly braces.
<div class="card" ng-repeat="app in apps">
<app-info info="app"></app-info>
</div>
But if I was not using a directive I think I would access the information like this. AngularJS documentation.
<div class="card" ng-repeat="app in apps">
{{ app }}
</div>
Could someone explain why I do not need the curly braces to help me better understand AungularJS. Thanks!
Usage of interpolation symbols {{ }}depend upon the implementation of the directive.
Some directives like ng-click='expression' or ng-if='expression' take an expression without the double curlies.
Whereas some other directives such as ng-src='{{expression}}' accept interpolation symbol.
It all depends upon how the directive is setup.
The basic usage of interpolation is to execute the expression and replace the content with the return value of expression (a string value).
As you learn more about the directives, you will learn how parameters are passed to directives using #,=,&. These parameters could be a simple string value (in which case an interpolation can be used), or an object, or a function.
In that particular case, using {{data}} you are evaluating the value of that variable, but when you do info="app" in other directive which contains a scope variable called info , what you are doing is binding the info scope variable of our app-info directive to the controllers (or parent directive) app scope variable.

Angular : How does ng-click directory parses the expression without doubly curly brace?

I have a view as follwing,
<li ng-repeat="img in people.images">
<img ng-src="{{img}}" ng-click="setImage(img)">
</li>
Its working. But my doubt here is, the attribute ng-click should have been set the img inside doubly braces to be executed as in ng-src as ng-click="setImage({{img}})". Its shown below,
<li ng-repeat="img in people.images">
<img ng-src="{{img}}" ng-click="setImage({{img}})">
</li>
But the later is not working.
How the expression is parsed here and how does ng-click vary from ng-src?
I really confused here. Any help highly appreciated.
The difference is the following: Some of the directives use expressions, some don't. This is how they "vary" from each other. You may use the angular documentation to see, which directive use expressions and which don't.
Example for ng-click: https://docs.angularjs.org/api/ng/directive/ngClick It uses an expression:
Example for ng-src: https://docs.angularjs.org/api/ng/directive/ngSrc It doesn't use an expression:
ngClick lets you define a JavaScript-like expression, while ngSource lets you define an usual String, where you also may define an expression, inside the double braces. According to the AngularJS documentation, everything inside of the double braces is also an expression: https://docs.angularjs.org/guide/expression.
I think that the "need" to have the difference between "Expression" for "ngClick" and "String" for "ngSrc" come from the original attributes they derive from: onclick and src.
The attribute src is used to reference a resource as String, while using the attribute onclick, you may use javascript. The usual case is to call a function in onclick, i.e. onclick="doSomething();". I assume that angularjs uses these attributes as a base, this is why the workflow is similar. ngClick lets you use usual javascript expressions, while ngSrc lets you use a String and add a {{}} expression if you need to.
The benefit of using ngSrc with a variable, for example ngSrc="http://localhost/{{myRessource}}" is, that it is evaluated only after $scope.myRessource is set, not before. It uses the observer pattern to render the view as soon as the variable is set, as far as I know.
According to your example, the second one which doesn't work:
<li ng-repeat="img in people.images">
<img ng-src="{{img}}" ng-click="setImage({{img}})">
</li>
It doesn't work because of a syntax error. ngClick uses javascript expression, and the syntax of setImage({{img}}) is not correct - you would not use double brackets around variables either in a javascript function.
Further: $interpolate and $parse
Like stated above, some directives, like ngClick use expressions, while other directives like ngSrc use plain Strings combined with {{}}. The difference between the two on angularJs side is the following:
a directive using an expression is evaluated by angularjs using $parse (Read here from heading "Text and attribute bindings")
a directive using a String is evaluated by angularjs using $interpolate (Read here from heading "Context")
Example:
$scope.varOne = "asdasdasd";
var test1 = $interpolate("http://localhost/{{varOne}}");
$scope.displayOne = test1($scope);
At first, we declare a variable varOne. $interpolate returns a function which needs to be called with the scope, we will bind this to the local variable test1. Then we will call test1 using the $scope. As a result, we will have on displayOne the String http://localhost/asdasdasd.
var test2 = $parse("1+5-3");
$scope.displayTwo = test2($scope);
$parse is evaluating javascript expressions, as a test we may use the calculation "1+5-3". After calling test2, the result will be 3.
I prepared a fiddle, so you can see this: http://jsfiddle.net/wSN54/6/
You may also try using brackets in the $parse evaluation (the same that happens in your second example):
$scope.varTwo = 2;
$scope.varThree = 3;
var test2 = $parse("{{varTwo + varThree}}");
$scope.displayTwo = test2($scope);
This must resolve in an error, because the double braces are not used in usual javascript expression:
Check it out fiddle: http://jsfiddle.net/wSN54/8/
As far as I know, if you put img param inside double brackets, when the page is rendered, you will notice that the parameter inside setImage function is a value of img. If you put img without brackets you will have rendered "setImage(img)" and in both case that will work.
Example:
imagine that you have one item in people.images model, and its for example "example.jpg". If you use brackets in setImage function, when the page is rendered you will see the attribute "ng-click=setImage('example.jpg')", in another approach you will have "ng-click=setImage(img)". In first case AngularJS don't need to parse value from your parameter, because you already put 'example.jpg' like a parameter, in another case AngularJS will parse value from img parameter/item before your function is executed.
TLDR; ng-src $interpolate the argument as template where ng-click $parse the expression
Long version
Copied from angular official docs
param=ngSrc, type=template
param=ngRepeat, type=repeat_expression
details refer to https://docs.angularjs.org/api/ng/directive/ngSrc and https://docs.angularjs.org/api/ng/directive/ngRepeat
What is expression - https://docs.angularjs.org/guide/expression
What is template(markup) - https://docs.angularjs.org/api/ng/service/$interpolate

Angular Isolate Scope and Attributes

In the following plunk:
http://plnkr.co/edit/ss3HTb?p=info
I am attempting to bind an attribute to an isolate scope. However, it is not working. I'm wondering if anyone knows why that is?
I've looked through several resources, including:
Need some examples of binding attributes in custom AngularJS tags and http://www.sitepoint.com/practical-guide-angularjs-directives-part-two/
You specified the isolate scope as
scope: {
attr: "=attributeName"
}
What that does is take the value of attributeName specified in your html as an expression in your scope and bind that to attr in your directive scope. But what you did was just to specify "hello" without having a hello object in your scope. To get it to work the way you have it now, you have to use the # attribute binding like so:
scope: {
attr: "#attributeName"
}
The other change that you need to do is how you specify the value in the html. You use titleCase when you define the attribute, but in the html instead of titleCase you need to seperate the "words" by a dash and use all lowercase. So attributeName becomes attribute-name
<node attribute-name="hello"></node>
On the other hand, if you actually want to bind to the value of an object in your scope, then make sure that you specify it in your scope and then you can use it in your directive (and preferably use the dot notation).
I have you updated your plunker to show you how they work.

Categories