Assume that I have two objects in my model: foo that can take two values Foo1 and Foo2 and object bar with two possible values Bar1 and Bar2.
Now, I would like to apply to my div classes based on values of these objects.
Basically, I would like to apply MyclassFoo1 when foo=Foo1, MyclassFoo2 when foo=Foo2 and similarly for bar.
For instance, if foo=Foo1 and bar=Bar2 I would like to end up with
<div class="MyClassFoo1 MyClassBar2"></div>
The two problems that I am having here are:
the class names are generated dynamically based on object values
Foo classes are independent from Bar classes
I've tried to use the syntax
<div ng-class="{class1: expr1, class2: expr2}"></div>
but it doesn't work, as the dictionary keys cannot be composed as 'MyClass' + foo
The other syntax
ng-class="{expr_val1: class1, expr_val2: class2}[expr]"
does not look promissing either: I would have to put all the foo-bar combinations as expression values.
Is there any other way to achieve my goal?
I've managed to solve the problem entirely in template, using the list notation in the following way:
ng-class="[foo ? 'MyClass' + foo : '', bar ? 'MyClass' + bar : '']"
You can put arbitrary angular expressions into the list.
Have you tried the following?
<div class="MyClass{{model.foo}} MyClass{{model.bar}}">
Even if model.foo or .bar becomes null this will add a non-existing class, which should not matter.
Notice that if you want a minus (-) sign in your class name, you should quote the class name (check out 'second-class').
Also you can bind availability of the class name to a function. Function should return boolean.
<div ng-class="{first: hasFirst, 'second-class': hasSecond(), third: true, fourthClass: obj.property == value}"></div>
I've found another way!
$scope.foo = 'fooClassName';
<div ng-class="foo"></div>
gives you
<div class="fooClassName" ng-class="foo"></div>
This works for me, using array in the View:
just do:
<div ng-class="[class1, class2]"></div>
I have tried this way and it worked but only drawbacks is it will not updates dynamically when you change the modules
<div ng-class="{'{{class1}}': expr1, '{{class2}}': expr2}"></div>
Related
is there any difference between className = 'name' and className = {'name'} in React? I ofc know that you can use variables in {}, but my question is specifically to string in those brackets {''}. I tried to simulate this in code and it looks to me that are both the same. Can anyone confirm this?
There is no difference in both the notations if you are writing a single class name that is, className="name" is equal and the same as className={'name'}
However, we use this {} notation when we want to give a conditional class. For example:
<p className={this.state.hidden ? "hidden" : ""}>Hello World</p>
The above line gives the <p> tag a class of hidden if the state variable hidden is set to true. We use the the curly braces {} in React when we want to write JavaScript code in the render function. We could use it for concatenation of two string class names or conditional class names.
No, there is no difference. When you write {'name'}, it is interpreted as 'name'. Just like if you write {'name' + ' name2' }, it is interpreted as 'name name2'.
Is there a way to append a property from this.props to an HTML element's attribute that already exists, and to do it inline (in the name of code-simplicity), without any variables/addons?
Something like this (but obviously this one and few other ways that I tried to append didn't work for me):
render() {
return (
<div className="entity" id="ent"+{this.props.index}>bla</div>
);
}
I do know that I could declare a variable before, append the prop to it and then use it as the attribute, but I have many lines like this and it will make my code bigger than I wanted it to be.
Thanks.
You can concatenate attributes as you usually do with strings:
<div className="entity" id={"ent" + this.props.index}>bla</div>
or (es6 syntax)
<div className="entity" id={`ent${this.props.index}`}>bla</div>
id={"ent" + this.props.index}
Or using interpolation instead of string concatenation.
id={`ent${this.props.index}`}
I think I have some sort of special code here as all I could google was "too simple" for my problem and it also didn't helped to come to a solution by myself, sadly.
I got a radio button group of 2 radios. I am iterating over "type" data from the backend to create the radio buttons.
My problem is the data binding: When I want to edit an object its "type" is set correctly, but not registered by the view so it doesn't select the desired option.
Follwing my situation:
Backend providing me this as "typeList":
[
{"text":"cool option","enumm":"COOL"},
{"text":"option maximus","enumm":"MAX"}
]
HTML Code:
<span ng-repeat="type in typeList track by type.enumm">
<input
type="radio"
name="type" required
ng-model="myCtrl.object.type"
ng-value="type">
{{type.text}}
</span>
Some Explanation
I don't want to use "naked" texts, I want to use some sort of identifier - in this case it is an enum. The chosen value shall be the entire "type", not only "type.text" as the backend expects type, and not a simple String.
So all I do with this is always a package thingy, the type.text is for like formatted/internationlized text etc.
A Pre-Selection works by setting this in the controller: this.object.type = typeList[0];
The first radio button is already selected, wonderful.
But why isn't it selected when editing the object. I made a "log" within the HTML with {{myCtrl.object.type}} and the result is {"text":"cool option","enumm":"COOL"}. The very same like when pre selecting. I already work with the same "technique" using select inputs, and it works fine. I also found some google results saying "use $parent because of parent/child scope". But 1) I didn't get that straight and 2) think it is not the problem here, as I use a controllers scope and not the $scope, or is this thinking wrong?
It might be explained badly, sorry if so, but I hope someone 1) get's what I want and 2) knows a solution for it.
Thank you!
If you're trying to bind to elements from an array, I believe you need to assign the actual elements from the array to your model property.
So this creates a new obj and sets it to $scope.selectedType (not what you want):
$scope.selectedType = {"text":"cool option","enumm":"COOL"};
whereas this assigns the first element of the array (which is what you want)
$scope.selectedType = $scope.typeList[0];
So to change the model, you can lookup the entry from the array and assign it to your model with something like this
$scope.selectedType = $scope.typeList.filter(...)
Here's a quick example of this approach http://plnkr.co/edit/wvq8yH7WIj7rH2SBI8qF
I have a problem finding the way to style a button according to it's state.
I have a question, and four answer tiles.
each tiles is coded like this:
<div class="button-default" ng-model="btn0" ng-click"evalAnswer(answer, btn0)">{{answer}}</div>
<div class="button-default" ng-model="btn1" ng-click"evalAnswer(answer, btn1)">{{answer}}</div>
<div class="button-default" ng-model="btn2" ng-click"evalAnswer(answer, btn2)">{{answer}}</div>
<div class="button-default" ng-model="btn3" ng-click"evalAnswer(answer, btn3)">{{answer}}</div>
On the controller side I have a function that, on click, look at the answer and return "good" if the answer is correct, and "nope" if the answer is not good.
What I would like is to add button styling within these good and nope states so the button become red in case the answer is nope, and green if it's the good answer. I already created the class and I only need to change "button-default" to "button-good" or "button-wrong". Also, It needs to change only the clicked button.
Any idea on the way to do that?
Use ng-class directive that should switch class according to any condition
In your case for two cases it should be something like:
<div ng-class="{'true':'button-default','false':'button-unique'}[btn0.state == 'One']"
ng-model="btn0"
ng-click="evalAnswer(answer, btn0)">{{answer}}</div>
If you want to use multiple cases:
<div ng-class="{'button-default':btn0.state == 'One','button-some':btn0.state == 'Two','button-else':btn0.state == 'Three'}"
ng-model="btn0"
ng-click="evalAnswer(answer, btn0)">{{answer}}
</div>
Demo Fiddle
There are multiple ways to accomplish what you are wanting:
ng-class use to set classes based on conditions
ng-style used when you can not define a class or just need to change simple css
I suggest using ng-class if the styling is complicated or multiple changes are needed in the css. the ng-class accepts an expression that can be evaluated to an array of class names, a string of delimited class names or a map of object names.
I think something like this should work for two classes:
<div ng-class="{{'someBoolean' && 'class-when-good' || 'class-when-nope'}}">{{answer}}</div>
or a ternary (using angular version above 1.1.5)
<div ng-class="'someBoolean' ? 'class-when-good' : 'class-when-nope'">{{answer}}</div>
Note if you need to apply a default class in addition to a conditional class this is how to would be done:
<div ng-class="{{'someBoolean' && 'class-default class-when-good' || 'class-default class-when-nope'}}">{{answer}}</div>
or a ternary with default
<div ng-class="'someBoolean' ? 'class-default class-when-good' : 'class-default class-when-nope'">{{answer}}</div>
The other option and the one I think might work best for your problem is the ng-style. Since you are only needing to change the button color in might be better to simply change that color rather then apply different classes.
<div ng-style="answer === 'good' && {'background-color' : 'green'} ||
answer === 'nope' && {'background-color' : 'red'}">{{answer}}</div>
assuming: that the {{answer}} is set to the values evaluated (answer is good or nope).
Edit:
For the style conditional it needs to be set in your controller, if answer can not be used in the conditional test. It looks like you have an object btn0, and each of those objects could have a property (btn0.isGood) the could be set in the evalAnswer(answer, btn0) click event and would result in the changing the style.
I have the component and have a problem setting the css class to it.
I want it to always have a class of "box", then to have additional classes specified by the directive "class" argument and one conditional class "mini".
Conceptually what I want to achieve is something like this:
<div class="box {{class}}" data-ng-class="{mini: !isMaximized}">
...
</div>
The problem is that when I set the class html attribute, the ng-class attribute is omitted.
How to make my example work without changing the controller? Is it even possible, or should I set the class in the controller instead (which I wish to avoid)?
A quick solution would be define the box class inside ng-class attribute:
<div data-ng-class="{mini: !isMaximized, box: true}"></div>
If you want to include a scope variable as a class, you can't use ng-class:
<div class="{{class}} box {{!isMaximized && 'mini' || ''}}">
Angular expressions do not support the ternary operator, but it can be emulated like this:
condition && (answer if true) || (answer if false)
I needed multiple classes where one was $scope derived and others were literal classes. Thanks to the hint from Andre, below worked for me.
<h2 class="{{workStream.LatestBuildStatus}}"
ng-class="{'expandedIcon':workStream.isVisible, 'collapsedIcon':!workstream.isvisible}">{{workStream.Name}}</h2>
Edit: for newer versions of Angular see Nitins answer as it is the best one atm
For me, this worked (I'm working on AngularJS v1.2.14 at the moment so I guess 1.2.X+ should support this, not sure about the earlier versions):
<div class="box" data-ng-class="{ {{myScopedObj.classesToAdd}}: true, mini: !isMaximized }"></div>
I replaced your {{class}} with {{myScopedObj.classesToAdd}} to show that any scoped variable or even a bit more complex object can be used this way.
So, every DIV element crated this way will have "box" class and any class contained within myScopedObj.classesToAdd (useful when using ng-repeat and every element in the array needs to have a different class applied), and it will have the "mini" class if !isMaximized.
Another way to do this without double curly braces and includes scope variables, tested with angular v1.2+.
<div ng-class="['box',
aClass,
{true:'large': false: 'mini'}[isMaximized]]"></div>
It's also rather nice because the variable can use different types as a index without increasing complexity using ternaries. It can also remove any need for negations ;)
Here is a fiddle link
You can use simple expression given below
ng-class="{'active' : itemCount, 'activemenu' : showCart}"