Complex angular js ng-class - angularjs

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}"

Related

ISML conditional CSS class declaration

I'm new to SFCC and I was wondering what is the best practices with writing conditional CSS classes in the ISML template. I couldn't find anything in the documentation specifically for element parameters but I have seen some code which works but doesn't look right to me.
<div class="foo <isif condition="${bar}">baz</isif>"></div>
Is this the right way to conditionally add a CSS class?
This is the documentation I've found for isif
https://documentation.b2c.commercecloud.salesforce.com/DOC1/index.jsp?topic=%2Fcom.demandware.dochelp%2FScriptProgramming%2FDemandwareJavaScriptExpressionsinISML.html
This variant is a little bit shorter
<div class="foo ${bar ? 'baz' : 'someting else'}></div>
From my understanding you first need to write the isml condition and inside it the html div, something like this:
<isif condition="${bar}">
<div class="foo">baz</div>
</isif>">
I'm only a couple months new to SFF so forgive me if I'm wrong.

display current value of ng-class in AngularJS

I have to track down a bug related to work of ng-class (sometimes it adds new value without removing old).
So I need a quick reference to see it's current value.
Is there any short (or not) way to bind that to the content?
I mean something like this:
<div ng-class="something">
{{ngClassValueDisplayedHere}}
</div>
I had exactly the same problem with ng-class not removing old value. After days of investigation it turned out that it was ngAnimate who was messing with class changes. removing it from angular module dependencies solved the problem (Angular 1.3).
ng-class can bind to many different things. From the documentation:
Expression to eval. The result of the 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 example, just display whatever your something is. It's supposed to be an angular expression, which can be evaluated like any other with double-curlies. This will help you debug your ng-class
<div ng-class="something">
{{something}}
</div>
Demo
In case someone else stumbles upon this problem like I did just recently with angular version 1.5.8: https://github.com/angular/angular.js/issues/14582
P.S. Update to 1.5.11 solved the issue related to ngAnimate, prior versions still had the same issue.

change button style according to state angularjs

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.

Evaluating moustache expressions after the page was initialized (dynamic binding)

I have a HTML-Document containing moustache expressions that angular-dart evaluates very well:
</head>
<body ng-cloak>
<ctrlTextElements>
<div id="stage">outside: {{ctrlTextElements.test1('three')}}</div>
</ctrlTextElements>
I want to dynamicaly add some HTML with moustache expression like so:
CtrlTextElements.addTextElement(mousePos.x, mousePos.y);
var div = dom.querySelector('#stage');
HttpRequest.getString("../path/text.html").then((r) {
div.children.add(new Element.html(r, validator: new AllowAllValidator()));
});
The content of the added text.html looks like this:
<div>inside: (not evaluated): {{ctrlTextElements.test1('three')}}</div>
That's the result in the browser:
outside: three
inside: (not evaluated):{{ctrlTextElements.test1('three')}}
How can I reevaluate the moustache expressions inside content that has been applied after the page was loaded?
The problem is that you are mixing jQuery like logic with angular logic here : manipulating the dom 'by hand' is rarely a good solution.
The problem here is that your newly added binding has not been compiled by angularjs = it has not been indexed as a directive that should be watched for and updated when scope changes.
Either you try a more angular way, for example using ng-hide or ng-repeat directive to display your content according to the controllers $scope (or another custom directive), or you try to $compile your newly added directive ( but this is bad ) : https://docs.angularjs.org/api/ng/service/$compile .
Maybe try in your controller :
$scope.$compile( div );
Not sure of the syntax though. Maybe you would need to write
<span ng-bind="..."></span>
instead of
{{ ... }}
to make it work.
#Alexhv is right. Sorry for my previous answer. I assumed it is about Polymer. Was already time for bed.
You can find a code example in my answer to this question: setInnerHtml doesn't evaluate Mustache
The pub package bwu_angular (http://pub.dartlang.org/packages/bwu_angular) contains this code as a Decorator (Directive) named bwu-safe-html

Conditional outer tag in a directive (i.e. <strong>)

I like a directive that conditionally puts a tag outside some content (but always prints the content), like this:
<p><strong ng-if-always-keep-inner-content="model.condition">{{model.text}}</strong>/p>
so if condition is true I get
<p><strong>yada yada</strong></p>
otherwise I get
<p>yada yada</p>
I could write it myself, but I want to know if it is possible to do with built in directives/options.
I should perhaps say this is used together with Bootstrap, which afaiu recommends using <strong> vs some class with a bold font.
I don't think there is a built in directive. You should write it.
I suggest to use a classic ng-if
<p ng-if="model.condition"><strong>{{model.text}}</strong></p>
<p ng-if="!model.condition">{{model.text}}</p>
In your specific case, you can also use ng-class and set the strong style via css.

Resources