complex ng-class expression containing both a value and a conditional - javascript

Say I wanted to have an ng-class do two things:
1) populate a value from a variable like so
`ng-class="myAwesomeJavaScriptVariable"`
and
2) conditionally set a predefined class:
`ng-class = "{awesomeClass: myAwesomeBoolean}`
I am aware that I could do something like
class="{{myAwesomeJavaScriptVariable}}" ng-class="{awesomeClass: myAwesomeBoolean}"
How (if this is even possible) could I amalgamate those two into a single ng-class expression?

I think it might be:
data-ng-class = "{ myAwesomeJavaScriptVariable, awesomeClass: myAwesomeBoolean }"
Alternatively:
class = "{{ myAwesomeJavaScriptVariable}} left clearfix" data-ng-class="{awesomeClass: myAwesomeBoolean }"

#Abraham P:
To Set Both the Conditional Statement and Scope Variable as Class
ng-class="[{awesomeClass: myAwesomeBoolean},myAwesomeJavaScriptVariable]"
This Will Work Fine.

Related

Add/Remove 'attributes' based on Angular variables or evaluated expressions in angularjs

i know ng-class can add/remove 'classes' based on Angular variables
or based on evaluated expressions. But if i want to say put an attribute like 'readonly' on an element based some variable in the controller, what is the simplest method. I wish a directive like 'ng-attr' exists.
for readonly you can use ngReadonly: https://docs.angularjs.org/api/ng/directive/ngReadonly
for more general solution check ngAttr: https://docs.angularjs.org/guide/interpolation

ngClass - creating a class name containing angular expression

I would like to create class names based on an the evaluation of an angular expression, but it seems that angular is removing these expressions from the eventually compiled classes. When iterating over cells, assume the following code:
<td ng-class="{'label{{cell.count}}': !!cell.count}"></td>
My goal is that when cell.count = 1 the resulting class will be "label1", when cell.count = 2, "label2", etc.
In practice, what happens is that angular discards the expression in the eventual class - As long as !!cell.count, I get the class "label" regardless of the count. How can I achieve this?
Try this:
<td ng-class="{'label'+cell.count: !!cell.count}"></td>
If it gets too complicated you can also move the entire object out into a function in the scope.
<td ng-class="getCellClass()"></td>
and then:
$scope.getCellClass = function() { ... }
Your problem is that the {{...}} substitution isn't appropriate here. You have to use an angular expression to create the object, or if you call a method on the scope you can do any javascript you need to create it.
Did you ever try: <td ng-class="'label' + cell.count"></td> - simply not using the curly braces works for me in my project (angular 1.5).
I had the same issue. I managed to solve it like this:
<td ng-class="{['label' + cell.count]: !!cell.count}"></td>

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

multiple expression using ng-class to set and remove class

I saw others' solution but mine didn't work, probably there are snytax error because I'm applying multiple class.
ng-class="{'col-md-9 col-sm-8 col-xs-8':item.lp_image!='', item.lp_image='','col-md-12'}"
What you are defining in the ng-class attribute is a JavaScript object. You can define several rules, just like you define several properties of an object. Each key is a class, each value is a boolean or an expression that gives a boolean.
E.g.
{
'class1': false,
'class2': true,
'class3': 2 == 2,
'class4': 3.1415 > 0
}

Using filters inside a ternary operator in AngularJS

Is there a method for applying a filter to a variable in the template when it is part of a ternary operation?
<img ng-src="{{ image_url && image_url|filter:"foo" || other_url }}">
In this case the filter is a custom filter, but one that I don't want to modify to handle the ternary operation (because the filter maybe different depending on where it's used and I don't want to reimplement that logic a bunch of times).
Liviu T. is probably right in most cases: you'd want to create a function on the scope that returns the right data for you in this case.
That said, you can get by by wrapping the filtered expression in parens:
image_url && (image_url | filter:"foo") || other_url
Fiddle

Categories