Angular.js - Understanding what statements can go in an ng-class query - angularjs

The Angular docs are really sparse on what is acceptable in an "expression" within a conditional ng-class.
For example, I'm running an ng-repeat over a list:
<ul class="clothes">
<li ng-repeat="piece in clothes | filter:query">
{{piece.name}}
</li>
</ul>
On every third <li> element I'd like to add a class of "third". Can this be done using ng-class with something like ng-class="{third : li:nth-child(3)}" or similar?
Side-note, is there a general reference somewhere that defines and gives examples of what can be used in an Angular expression? There's some really basic stuff that I can do with vanilla Javascript/css but I can't work out how to cram it into Angular!

Just create an expression that evaluates to true or false, a bit similar to Javascript expressions but with some differences, you can read about it here.
<ul>
<li ng-repeat="item in items" ng-class="{third: !(($index+1)%3) && !$first }">{{item}}</li>
</ul>
Here is a jsBin.
In my code I am telling ng-class to add the class 'third' when ($index+1)%3 is zero and it is not the $first list item ($index, $first and $last are created by ng-repeat).

if you want to use css instead of angular for the styling, you can use the css nth selector
http://www.w3schools.com/cssref/sel_nth-child.asp
li:nth-child(3n+3)
{
background:#ff0000;
}

Related

Angular Directive with Replace=false creates list html that is non semantic

We are thinking about moving to directives that use replace=false, as I hear replace=true is being deprecated. One problem I cant figure out how to fix, is for all directives that are based on lists, the resultant html is not semantic.
For example a list directive might be something like:
<tg-list tg-compact="true">
<tg-list-item>foo</tg-list-item>
<tg-list-item>bar</tg-list-item>
</tg-list>
this will currently (with replace=true) compile to:
<ul class="o-list o-list--compact">
<li class="o-list-item">
foo
</li>
<li class="o-list-item">
bar
</li>
</ul>
with replace=false we will end up with either:
<tg-list class="o-list-icon o-list-icon--compact">
<ul>
<tg-list-item>
<li class="o-list-item">foo</li>
</tg-list-item>
<tg-list-item>
<li class="o-list-item">bar</li>
</tg-list-item>
</ul>
</tg-list>
or:
<tg-list class="o-list-icon o-list-icon--compact">
<tg-list-item>foo</tg-list-item>
<tg-list-item>bar</tg-list-item>
</tg-list>
The first is bad because it is definitely non semantic, the second is bad because although it is "semantic" (as in html5, custom tags are ok), we lose anything that ul>li would have given us (a screen reader, for example, may have special ways to treat them).
Perhaps we can use the html5 'role' attributes? But if so i think the list item would need add the role to the element in the link function?
Dunno, but how have you lot solved this?
You can configure directives to have restrict set to A which stands for attribute. That way you can use it as:
<ul tg-list tg-list-compact=true>
<li tg-list-item>
foo
</li>
<li tg-list-item>
bar
</li>
</ul>
So what I did in the end is make the list-item wrap itself in an "li" in its link function.
The list-item link:
public link = ($scope: angular.IScope, $element: angular.IAugmentedJQuery) => {
$element.wrap('<li></li>'); }
Pretty simple in the end, but makes the html much more symantic so i am happy. Shout out to Sander for the help

Can I have two ng-repeat values, where one applies when boolean is true?

I have an element that is repeated.
<li ng-repeat="plan in displayedPlans"> ... </li>
I'd like to add limitTo to it to show the first two plans.
<li ng-repeat="plan in displayedPlans|limitTo:2"> ... </li>
But now I want limitTo to only apply if a boolean (called "experiment" in this example) is true. One of the ways I tried to accomplish my goal is something like this (which didn't work) -
<li ng-repeat="plan in displayedPlans, plan in displayedPlans|limitTo:2 : experiment"> ... </li>
I also tried putting the ng-repeat value in curly braces and separating the two options with || but that didn't work. I'm wondering if there is a clean solution I can use in the HTML.
Change the value of limitTo depending on experiment. It its true set it to 2, else 10000.

Is there any directive that acts like a "with" in angular?

Say you have an object yourObject on the scope and you want to access some deep properties like the following :
<ol>
<li ng-bind="yourObject.thing.map.one"></li>
<li ng-bind="yourObject.thing.map.two"></li>
<li ng-bind="yourObject.thing.map.three"></li>
</ol>
Is there any built-in directive that could make it look more like this:
<ol ng-with="yourObject.thing.map">
<li ng-bind="one"></li>
<li ng-bind="two"></li>
<li ng-bind="three"></li>
</ol>
UPDATE
A similar question was already. Please see Equivalent of {{#with}} in angular
One way I would do this scenario is by implementing a controller that will have a variables to those an array of one, two three... and then using ng-repeat to loop over that.
So for ng-controller, you could write, ng-controller="SomeCtrl as ctrl"
and then ctrl.arrayVariable would hold an array of all the data you want to show
To make matters very simple, you could use ng-repeat to loop through the data.
So, possibly, ng-repeat="var in ctrl.arrayVariable"
Anyways, I'm not sure exactly how your code is structured, but it should work in most instances.
Long story short, ng-repeat is awesome

use of ng-repeat with ng-class and $index

i need different classes to be used for each iteration, following code.
Edit: the index is within the li
<li class="table-view-cell bg_{{$index}}" ng-repeat="agenda in agendas">
<span class="cell">
<a data-href="#/agendas/{{agenda.id}}" ng-click="detail($event, agenda.id)">
<span class="type">{{agenda.date}}</span>
</a>
</span>
</li>
also Why do we need ng-class, could I not use simple class here?
Try to replace ng-classs with just class, and add track by $index in your ng-repeat.
Or skip track by. Not sure what you are trying to do but, this should get you going:
http://jsfiddle.net/clto/HB7LU/8072/
what about using css pseudo-class nth-child.
you can apply different css for each child by their index in your css, instead of just creating lots of different class names for each index.

Static list item inside ngRepeat

So,
I am rendering a basic list using ngRepeat, but need the first <li> to be static content, rather than being generated from the data array:
e.g.
<ul ng-repeat="item in items">
<li>This is text from the template and will always be the same.</li>
<li>{{item}}</li>
</ul>
I've also looked at using ng-repeat-start, but just can't quite get to a solution.
It is a common misconception that people want to use ng-repeat on the parent element, when in fact you use it on the actual elements that do the repeating.
You just need to change it to:
<ul>
<li>This is text from the template and will always be the same.</li>
<li ng-repeat="item in items">{{item}}</li>
</ul>

Resources