Angular Expression Interpolation - angularjs

I came through the following example of ng-class="expression" in a book.
http://plnkr.co/edit/fJGT5L9HZXvgAiAyXwlW?p=preview
ng-class="{error:isError,warning:isWarning}"
I get the controller logic, but my doubt is in the interpolation happening here.
What does the following scenarios mean (what is the evaluated value) and Why?
ng-class="{error:true,warning:true}"
ng-class="{error:true,warning:false}"
ng-class="{error:false,warning:true}"
ng-class="{error:false,warning:false}"

From the ngClass arguments docs:
The result of the arguments evaluation can be a string
representing space delimited class names, an array, or a map of class
names to boolean values. In the case of a map, the names of the
properties whose values are truthy will be added as css classes to the
element.
So in your case the result of the arguments after evaluation is a map which produces:
ng-class="{error:true,warning:true}"
=> class="error warning"
ng-class="{error:true,warning:false}"
=> class="error"
ng-class="{error:false,warning:true}"
=> class="warning"
ng-class="{error:false,warning:false}"
=> no class attribute

ng-class="{error:true,warning:true}" => class="error warning"
ng-class="{error:true,warning:false}" => class="error"
ng-class="{error:false,warning:true}" => class="warning"
ng-class="{error:false,warning:false}" => no classes set
As you could notice ng-class get just hash where keys are names of classes and values -- conditions (if true than class will be added to class attribute)
So, ng-class just uses angular expression and check what data it returns (string, array or hash-map) then it applies certain parser to get final classes array to put it to class. One of this is described above.
Angular expressions
Angular like as Javascript uses eval mechanism to execute code (expression), but unlike JS Angular uses safe eval called $eval([expression], [locals]) (Docs)
I'm strongly recommending you to read this article about Angular expressions to understand how it works.

Angular will add (or append to the existing class attr) the following class attribute to the element:
class="error warning"
class="error"
class="warning"
No class attribute added

Related

What is the active:true construct in Angular js?

I am following the phonecat Angular tutorial here and I was wondering what this code was doing:
<div class="phone-images">
<img ng-src="{{img}}"
class="phone"
ng-repeat="img in phone.images"
ng-class="{active:mainImageUrl==img}">
</div>
Is {active:true} an angular construct? If so, what does it do and where is the documentation? Why the single {}?
Will {{img}} work in ng-src even though it's above the ng-repeat line?
ng-class is a directive, that expects an Angular expression. The type of the expression can be a string (the name of the class), an array of strings (the names of the classes), or an object where keys are the names of the classes, and values are booleans telling if the class must be added or not.
In that case, the expression is a literal JavaScript object, just as you would write it in JavaScript code:
var object = {active: mainImageUrl == img};
And the CSS class 'active' will thus be added if mainImageUrl == img is true.

why do some angular examples have single handlebars and some have double handlebars?

Please note Double {{ }} :
http://docs.angularjs.org/api/ng.directive:ngMouseleave
Please note single Single: { }
http://docs.angularjs.org/api/ng.directive:select
Does it have something to do with "in the quotes" or "in the tag?" Please confirm. And does any one know why?
Of course the vast level of info on the handlebars site does not help:
The double braces are for one-way binding a model to the template, essentially stick the value of the model into that location.
The single braces signify what type of value the attribute expects. For example:
<select
ng-model="{string}"
[name="{string}"]
[required]
[ng-required="{string}"]
[ng-options="{comprehension_expression}"]>
</select>
ng-model expects a string
name (optional) expects a string
required (optional) expects no value
ng-required (optional) expects a string
ng-options (optional) expects an Angular comprehension expression
The string values can be Angular expressions
Versus this, which is just a direct binding:
<body>
<button ng-mouseleave="count = count + 1" ng-init="count=0">
Increment (when mouse leaves)
</button>
count: {{count}}
</body>
Where the value count on the scope replaces {{count}}
Both ways you provide a expression which are like javascript expressions.
HTML attributes that have been extended by angularjs and take an expression can take any expression without using interpolation symbol {{}}. Single {} is just to signify what should be provided.
Everywhere else you use interpolation {{}}
See documentation on expressions here http://docs.angularjs.org/guide/expression

Password Verification in angular js

I have a directives.js file in which i have my directives defined. I need to add one more directive for password verification.
I have gone thru lot of links. I am not able to succeed. From the below link,
password-check directive in angularjs
I am not able to understand how come 'data-password-verify' attribute refers to the definition of 'passwordVerify' directive?? where should the mapping be defined?
I've struggled with this, and it's messy. I see no help in a directive, because logically, all that's needed is to constrain one value to match another by validation. All I needed was ng-pattern and a helper filter to escape a string into a tight regular expression. (Note I'm checking emails, but the concept is identical.)
My code:
<input type="email" name="email" ng-model="data.email"
required placeholder="jane.doe#example.com">
<input type="email" name="verify" ng-model="verify"
required ng-pattern="data.email | quotepattern">
The quotepattern filter implementation is:
function(input) {
if (!! input) {
return "^" + input.replace(/(\W)/g, "\\$1") + "$";
} else {
return input;
}
}
This does a valid binding on both, and checks for validity. If the first value changes, both controls get updated. If the verify control value changes, only that control is affected.
To me, this is infinitely simpler than directive hackery, and conceptually more correct too, since logically all you need to do is check for a string match in the verify control. Engineering an entire new control with custom editing logic to do that is breeding an entire yak only to shave it.
In the following example, we say that the <input> element
matches the ngModel directive.
<input ng-model="foo">
The following also matches ngModel:
<input data-ng:model="foo">
Angular normalizes an element's tag and attribute name to
determine which elements match which directives. We typically refer to
directives by their case-sensitive {#link
http://en.wikipedia.org/wiki/CamelCase camelCase} normalized name
(e.g. ngModel). However, since HTML is case-insensitive, we refer to
directives in the DOM by lower-case forms, typically using {#link
http://en.wikipedia.org/wiki/Letter_case#Computers dash-delimited}
attributes on DOM elements (e.g. ng-model).
The normalization process is as follows:
Strip x- and data- from the front of the element/attributes.
Convert the :, -, or _-delimited name to camelCase.
Read the documentation

Angular's ng-class: combine enumerated (array) classes and condition-based ones?

I have an array with classes set in the controller (has to be this way, it's read from page's meta-template). I'd also like to have a conditional classes applied to the same element. Is it possible?
Edit, more info: my html element has classes that originate from two sources - one is a set of classes created by the controller (they are provided by a service outside of my code, I can't have them hardcoded in the view). The other source is an output of a condition (for example: if "$scope.activeElement === name_of_this_element, add 'active' class).
In ng-class directive, I can't use an object notation for unspecified list of classes (the first source) and I have to use an object notation for conditional classes.
Edit: found a solution (see below).
Another option is to write an ng-class in this way
<div ng-class="[item.class, item.errorClass, item.locked ? 'locked-item' : '']"></div>
I found a solution - I placed the "fixed" classes in a regular class attribute (converted that string to an array first) and conditional ones in ng-class object, like this:
<td ng-repeat="cell in row.cells" class="{{cell.cssClass}}" ng-class="{active: condition}">
The fact that you stored a array of classes' name is not relevant here.
HTML
<div ng-class="arrOfClasses[condition]"></div>
Angular
app.controller('myCtrl', function($scope) {
$scope.arrOfClasses = ['class1', 'class2', 'class3'];
$scope.condition = 1; // what ever number here
});
A good way, and also to avoid using {{}} inside class would be with just an expression:
<td ng-repeat="cell in row.cells" ng-class="(condition ? 'active ' : '') + cell.cssClass">

What is the difference between ng-click and data-ng-click in angularjs?

From 1st view seems like data-ng-click can pass some data as argument to method should be invoked during pressing on button.
But I don't see the difference.
I have followed snippets of code:
HTML
<input
type="button"
value="Fess"
ng-click="toggle(2)">
OR
<input
type="button"
value="Fess"
data-ng-click="toggle(2)">
JS
$scope.toggle = function (valueS) {
alert(valueS);
}
Both work.
Thanks,
They are the same thing. You can use data-ng-click to make a valid html.
From the angular docs on directives:
Directives have camel cased names such as ngBind. The directive can be
invoked by translating the camel case name into snake case with these
special characters :, -, or _. Optionally the directive can be
prefixed with x-, or data- to make it HTML validator compliant. Here
is a list of some of the possible directive names: ng:bind, ng-bind,
ng_bind, x-ng-bind and data-ng-bind.
Leaving them out is totally fine for practical purposes. It's just that if you run it through an html validator service, it will not pass as complliant.
HTML5 has an ability to embed custom data attributes on all HTML elements
These new custom data attributes consist of two parts:
Attribute Name
The data attribute name must be at least one character long and must be prefixed with 'data-'. It should not contain any uppercase letters.
Attribute Value
The attribute value can be any string.
<li data-spacing="30cm" data-sowing-time="February to March">Celery</li>
source : http://html5doctor.com/html5-custom-data-attributes/
Found a difference while using with and without Form.
When my element is in a Form they act the same.
When I use data-ng-click on an element not within a form, Click event is not happening.

Resources