Conditionally adding elements in ng-repeat block - angularjs

Is it possible to add stuff to the markup based on condition?
Like in this example, when I want to add td only on the first iteration (only for the first element of myData)?
<tr ng-repeat="m in myData">
<td>{{m.Name}}</td>
<td>{{m.LastName}}</td>
#if myData.indexOf(m) = 0 then // something like that
<td rowspan ="{{m.length}}">
<ul>
<li ng-repeat="d in days">
{{d.hours}}
</li>
</ul>
</td>
</tr>

Yes, AngularJS has 2 directives for this occasion:
The ng-show / ng-hide family of directives can be used to hide (by
using display CSS rules) parts of the DOM three based on a result of
evaluating an expression.
If we want to physically remove / add parts of the DOM conditionally
the family of ng-switch directives (ng-switch, ng-switch-when,
ng-switch-default) will come handy.
At the end of the day both solutions will give the same visual effect but the underlying DOM structure will be different. For simple use cases ng-show / ng-hide is probably OK, but larger portions of the DOM should be treated with ng-switch.
For the use case from this question I would advice using ng-switch.

The best solution should be:
<tr ng-repeat="m in myData">
<td>{{m.Name}}</td>
<td>{{m.LastName}}</td>
<td ng-if="$first" rowspan="{{myData.length}}">
<ul>
<li ng-repeat="d in days">
{{d.hours}}
</li>
</ul>
</td>
</tr>

Related

ng-options disabled in array

I have a view that manages school's tests in a period (trimester or semester). Each semester can have many tests of type normal but only one of type examen.
I have made a script in jsFiddle that shows the behavior I am looking for https://jsfiddle.net/dfLf9zkm/.
The difference is that in the ng-repeat I have a ng-controller over each test so every time I called the ng-method it only affects the row I am on and not the rest. Something like
<div ng-app="app" ng-controller="Controller">
<table>
<tr>
<th>Type</th>
<th>Ponderation</th>
</tr>
<tr ng-repeat="test in tests track by test.id" ng-controller="TestRow">
<td><select ng-model="test.type" ng-options="type.id as type.type disable when type.id == 2 && hasExam && idExam!=test.id for type in types" ng-change="checkTests()"></select>
</td>
<td>{{test.ponderation}}%</td>
</tr>
</table>
</div>
If I change the value of $scope.hasExam with a method inside TestRow controller it only affect that row and not the rest. How can I do it?
I finally decided to leave everything in one controller and that fixed everything up

Change display text based upon value

I am displaying Errors on my Html page using Angular JS. The problem is I am receiving only error codes from the HTML . What are the various ways in which i can change the error code to the the Error text i like
<table>
<tr ng-repeat='item in errorsd'>
<td align="left" class="validationMsg"> {{item.message}}</td></tr>
</table>
If my item.message has one . I would like to display Beginner ,if its 2 Intermediate like that and so on . Should i use ng-if ? should i use ng-switch or should i input some logic on the controller side .
Should i use ng-if ?
ng-switch is more readable and hence a better option. Later when you look back at the code it will be intuitive to you and other developers about what this code does.
should i input some logic on the controller side .
Why put a logic in controller-side if the framework already provides a solution for such use-case?
I would do it like:
<table>
<tr ng-repeat='item in errorsd'>
<td ng-switch="item.message" align="left" class="validationMsg">
<span ng-switch-when="1">Beginner</span>
<span ng-switch-when="2">Intermediate</span>
<!-- and so on.. -->
</td>
</tr>
</table>
I say use a switch statement inside of your controller.
So depending on the value, the global message would change thus displaying the correct one when triggering the validation msg box to show.

Angular vs-repeat performance issue with tables with 7k rows

I am using angular vs-repeat to render around 7k rows in a table. If I use vs-repeat for table body, the rendering was very slow.
<table class="table">
<tbody vs-repeat style="width: 100%;">
<tr ng-repeat="row in list track by $index">
<td>{{::row[listColumns[0].colName]}}</td>
<td>{{::row[listColumns[1].colName]}}</td>
<td>{{::row[listColumns[2].colName]}}</td>
<td>{{::row[listColumns[3].colName]}}</td>
<td>{{::row[listColumns[4].colName]}}</td>
</tr>
</tbody>
If I use vs-repeat without tables, in my case I used divs. Its rendering very fast
<div vs-repeat class="table-body">
<div class="row" ng-repeat="row in list track by $index">
<div class="col-md-4">{{::row[listColumns[0].colName]}}</div>
<div class="col-md-2">{{::row[listColumns[1].colName]}}</div>
<div class="col-md-2">{{::row[listColumns[2].colName]}}</div>
<div class="col-md-2">{{::row[listColumns[3].colName]}}</div>
<div class="col-md-2">{{::row[listColumns[4].colName]}}</div>
</div>
</div>
Please suggest how to improve performance for table?
With vast collections of items that render many DOM elements, even the most negligible processing of items inside an ng-repeat can choke your app.
DOM-related solutions that check if elements are in view don't tell you if nested components have been loaded and rendered completely, leading to errors.
My solution to this problem is angular's limitTo : limit: begin filter, along with iScroll or native scrollTop and scrollBottom callbacks, which raise or reduce the begin index in the controller according to the browse direction - sort of frontend pagination where only a specific number of items are shown at the DOM.
<tr ng-repeat="item in items | limitTo : 100 : 600 track by $index">
<span>{{ item.property }}</span>
</tr>
Then you can find the optimal limitTo number that work out best for the app - while keeping it light, quick, and agile as Angular should be.
use ng-repeat on small set of an array. Do pagination or lazy loading. store data to temporary array which you want to display rather having n-repeat on 7k records.
Thoughts?
Thanks!

Angular JS Nested ng-repeat for bootstrap badges

Im trying to tag different video items in a bootstrap table. I'm already using an ng-repeat to loop over the array of objects which store video data. I'm now trying to create a nested ng-repeat to loop over another array of "tags" within the ng-repeat that creates each table row.
I'm getting some weird results though. I was hoping that I could just put an ng-repeat on the td and then put the angular expression in a span with the boostrap class "badge". Any thoughts as to whats going wrong?
http://jsfiddle.net/jheimpel/6nh100ca/
<tr ng-repeat="topic in topics">
<td><a ng-href="#/{{topic.url}}"><i class="fa fa-play"></i></a></td>
<td>{{topic.topic}}</td>
<td>{{topic.date}}</td>
<td>{{topic.presenter}}</td>
<td ng-repeat="tag in topic.tags">
<span class="badge">{{topic.tags}}</span>
</td>
</tr>
Change it to
<span class="badge" ng-bind="tag"></span>
You're telling it to print out the array you're ng-repeating instead of the object the ng-repeat is giving you. Also ng-bind is better, see this

How to generate table tr from multiple overlapping ng-repeat

While replacing legacy javascript with angularjs code, I'm stuck with the following use case (simplified code as follows):
<tr ng-repeat="section in page.sections>
<td>{{section.name}}:</td>
</tr>
<tr ng-repeat="task in section.tasks>
<td>{{task.name}}:</td>
</tr>
The expected result should be a single table, with task rows should follow parent section row.
I understand that the inner loop won't work because of the scope of the section element is not the parent of the inner loop.
Is there a work around (or a best suitable way) to perform this?
The following should work:
<tr ng-repeat-start="section in page.sections">
<td>{{section.name}}:</td>
</tr>
<tr ng-repeat="task in section.tasks">
<td>{{task.name}}:</td>
</tr>
<tr ng-if="false" ng-repeat-end><td>end</td></tr>
See a demo plunkr

Resources