Incrementing number in angular View (cascaded ng-repeat) - javascript

I have similar kind of scenario as per the example below, and want to print serial number for each row independent of child, I.E. for each mark record.
Java script Object structure:
$scope.childsList = [
{
id:12346,
name : 'Sagar Kulthe',
marksList : [{subject:'Math', marks: 55}, {subject:'English', marks: 54},
{subject:'Biology', marks: 65},
{subject:'Physics', marks: 78}]
},
{
id:12346,
name: 'Amol Pawal',
marksList : [{subject:'Math', marks: 55}, {subject:'English', marks: 54},
{subject:'Biology', marks: 65},
{subject:'Physics', marks: 78}]
},
{
id:12346,
name: 'Tushar Shah',
marksList : [{subject:'Math', marks: 55}, {subject:'English', marks:
54}, {subject:'Biology', marks: 65},
{subject:'Physics', marks: 78}]
}
];
View:
<table>
<thead>
<th>Sr NO:</th>
<th>Name</th>
<th>Subject</th>
<th>Marks</th>
</thead>
<tbody ng-repeat="child in childsList track by $index">
<tr ng-repeat="mark in marksList track by $index" ng-init="marksIndex = $index">
<td>{{marksIndex }}</td>
<td>{{child.name}}</td>
<td>{{mark.subject}}</td>
<td>{{mark.marks}}</td>
</tr>
</tbody>
</table>

Below approach will help you,
https://plnkr.co/edit/CEbyJNevu94LBogYUek7?p=preview
<table ng-init="count[0] = 0">
<thead>
<th>Sr NO:</th>
<th>Name</th>
<th>Subject</th>
<th>Marks</th>
</thead>
<tbody ng-repeat="child in childsList track by $index" ng-init="count[+$index + 1] = +count[+$index] + child.marksList.length">
<tr ng-repeat="mark in child.marksList track by $index">
<td>{{count[+$parent.$index] + $index + 1}}</td>
<td>{{child.name}}</td>
<td>{{mark.subject}}</td>
<td>{{mark.marks}}</td>
</tr>
</tbody>

I suppose you have to change to this:
<td>{{mark.subject}}</td>
<td>{{mark.marks}}</td>
Also, i don't think you need to have ng-init directive, as $index is directly accessible. So, you can change to this:
Updated as per comment at other answer now deleted
Suppose this is the controller:
app.controller('appCtrl', ['$scope', function($scope){
$scope.counter = 0;
$scope.childsList = [
......
];
}]);
Now in the markup
<tbody ng-repeat="child in childsList track by $index">
<tr ng-repeat="mark in marksList track by $index" ng-init="marksIndex = $index">
<td>{{counter+1}}</td><!-- Will start as 1, 2, 3 -->
<td>{{child.name}}</td>
<td>{{mark.subject}}</td>
<td>{{mark.marks}}</td>
</tr>
</tbody>

I just do an example hope it can help you
Just need to change number 2 equal your markList length brother.
https://embed.plnkr.co/vkizqh213NN6aUeB9tgQ/

Related

Pass through bi-dimensional array with ng-repeat and $index

Having this input:
myArray = [
{name: "name1", id: 1, parameters: ["first", "second"]},
{name: "name2", id: 2, parameters: ["first"]},
{name: "name3", id: 3, parameters: ["first", "second"]},
];
I want to put it on a table to look similar to this:
I tried to do it, the first two columns are correct but the last one doesn't appear:
<tr ng-repeat="rows in $ctrl.name track by $index">
<td>{{$ctrl.name[$index]}}</td>
<td>{{$ctrl.id[$index]}}</td>
<td><span ng-repeat="rows in $ctrl.parameters[$index] track by $secondIndex">{{$ctrl.parameters[$index][$secondIndex]}}</span></td>
</tr>
The error message is
Error: [ngRepeat:dupes] Duplicates in a repeater are not allowed. Use
'track by' expression to specify unique keys.
So probably two ng-repeats aren't the solution but it don't know how to do this. Any ideas?
This should also work:
<tr ng-repeat="item in myArray">
<td>{{item.name}}</td>
<td>{{item.id}}</td>
<td>
<span ng-repeat="subItem in item.parameters">{{subItem}}</span>
</td>
</tr>
Well, you should use ng-repeat on myArray and then show whatever you want.
And to show the parameters in the desired format you can use row.parameters.toString().replace(',', ' ')
Please check the working snipppet
Thanks
var app = angular.module('myApp', []);
app.controller('ctrl', function($scope){
$scope.myArray = [
{name: "name1", id: 1, parameters: ["first", "second"]},
{name: "name2", id: 2, parameters: ["first"]},
{name: "name3", id: 3, parameters: ["first", "second"]},
];
})
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
td, th {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
tr:nth-child(even) {
background-color: #dddddd;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="ctrl">
<table >
<tr>
<th>Name</th>
<th>Id</th>
<th>Parameters</th>
</tr>
<tr ng-repeat="row in myArray">
<td>{{row.name}}</td>
<td>{{row.id}}</td>
<td>{{ row.parameters.join(' ') }}</td>
</tr>
</table>
</div>
The solution suggested by Aleksey Solovey solved the problem:
<tr ng-repeat="rows in $ctrl.name track by $index">
<td>{{$ctrl.name[$index]}}</td>
<td>{{$ctrl.id[$index]}}</td>
<td><span ng-repeat="rows in $ctrl.parameters[$index] track by $index">{{$ctrl.parameters[$parent.$index][$index]}}</span></td>
</tr>
Use this
<tr ng-repeat="rows in myArray track by $index">
<td>{{ rows.name }}</td>
<td>{{ rows.id }}</td>
<td><span ng-repeat="data in rows.parameters track by $index">{{ data+ " " }}</span></td>
</tr>

How to handle nested structures with ng-repeat using HTML tables in Angular 1.x

Let us assume we have following data structure:
var data = [
{
name: "item name",
nestedData: [{
name: "nested name",
quantity: 1
},
{
name: "nested name 2",
quantity: 2
}
]
},
{
name: "item name 2",
nestedData: [{
name: "nested name 3",
quantity: 3
}
]
}
];
Standard behavior of ng-repeat directive will iterate over high level elements. If we run ng-repeat="item in data" it will produce two items.
Is it possible - without using custom directive - to iterate over first item ("item name") twice (multiply it by a length of nestedData array)?
The output I'd like to achieve is:
<table>
<thead>
<th>Name</th>
<th>Nested name</th>
<th>Nested quantity</th>
</thead>
<tbody>
<tr>
<td rowspan="2">item name</td>
<td>nested name</td>
<td>1</td>
</tr>
<tr>
<td ng-hide="true">item name</td>
<td>nested name 2</td>
<td>2</td>
</tr>
<tr>
<td>item name 2</td>
<td>nested name 3</td>
<td>3</td>
</tr>
</tbody>
</table>
Nested ng-repeat is not suitable in this situation because there's a need to iterate over <tr>'s.
You can use a nested ng-repeat to get your desired result as it's valid HTML to have multiple tbody elements.
Here is a JSFiddle for a working example
<table>
<thead>
<th>Name</th>
<th>Nested name</th>
<th>Nested quantity</th>
</thead>
<tbody ng-repeat="item in data">
<tr ng-repeat="nestedItem in item.nestedData">
<td rowspan="{{item.nestedData.length}}" ng-hide="$index == 1">{{item.name}}</td>
<td>{{nestedItem.name}}</td>
<td>{{nestedItem.quantity}}</td>
</tr>
</tbody>
</table>
It's a different approach to achieve expected output.
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
var data = [
{
name: "item name",
nestedData: [
{
name: "nested name",
quantity: 1
},
{
name: "nested name 2",
quantity: 2
},
{
name: "nested name 3",
quantity: 3
}
]
},
{
name: "item name 2",
nestedData: [{
name: "nested name 3",
quantity: 3
}
]
}
];
var nestedData = [];
angular.forEach(data, function(item){
if(item.nestedData.length > 1){
angular.forEach(item.nestedData, function(nestedItem){
nestedData.push({
name : item.name,
nestedName: nestedItem.name,
nestedQty: nestedItem.quantity,
colspan: item.nestedData.length
});
});
} else {
nestedData.push({
name : item.name,
nestedName: item.nestedData[0].name,
nestedQty: item.nestedData[0].quantity
});
}
});
$scope.data = nestedData;
});
tr.multiple > td:first-child {
display: none;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script>
<div class="container" ng-app="myApp" ng-controller="myCtrl">
<table class="table table-stripped">
<thead>
<th>Name</th>
<th>Nested name</th>
<th>Nested quantity</th>
</thead>
<tbody>
<tr ng-repeat="item in data" ng-class="{'multiple': item.colspan > '1' && !$first}">
<td rowspan="{{item.colspan ? item.colspan : '1'}}">{{item.name}}</td>
<td>{{item.nestedName}}</td>
<td>{{item.nestedQty}}</td>
</tr>
</tbody>
</table>
</div>

How to make ng-repeat statement in angular JS run for a limited number of times

I have a table which is being populated like this :
<table>
<tr>
<th>Id</th>
<th>Details</th>
<th>Score</th>
</tr>
<tr ng-repeat="x in data.items">
<td><a href="{{ x.get }}">{{ x.id }}</td>
<td>
<p><b>{{ x.name[0] }}</b></p>
<p><u>Brand</u>: {{ x.Brand }}; <u>Category URL</u>: {{ x.mlnURL }};<u>Price</u>: Rs {{x.Price}} </p>
</td>
<td>
<p><b>{{ x.score }}</b></p>
Classifier Score: {{ x.cscore }} <br>
Document Score: {{ x.sscore }} </p>
</td>
</tr>
</table>
Now in this line
<tr ng-repeat="x in data.items">
instead of running foe all the x in data.items , i want to run it a limited number of times according to how the user wants . I have this number input from the user and stored in a variable . How can i achieve this .
Here you go:
<tr ng-repeat="x in data.items | limitTo: 2">
It will repeat 2 times with this code. You can change the 2 to a var on your scope.
You can utilize the filter limitTo, like the example below:
angular.module('myApp', [])
.controller('myCont', function($scope) {
var theItems = [{
name: 'walkman',
Brand: 'sony',
Price: 20,
explain: 'an AM/FM cassette player',
score: 89,
mlnURL: 'http://sony.com'
}, {
name: 'discman',
Brand: 'sony',
Price: 30,
explain: 'a CD player',
score: 83,
mlnURL: 'http://sony.com'
}, {
name: ['ipod'],
Brand: 'Apple',
Price: 200,
explain: 'an MP3 player',
score: 89,
mlnURL: 'http://apple.com'
},
{
name: ['Flash Player'],
Brand: 'SanDisk',
Price: 40,
explain: 'an MP3 player',
score: 79,
mlnURL: 'http://sandisk.com'
}];
$scope.data = {items: theItems};
$scope.limit = 2;
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCont">
# of items to show <input type="number" ng-model="limit"/>
<table>
<tr>
<th>Id</th>
<th>Details</th>
<th>Score</th>
</tr>
<tr ng-repeat="x in data.items | limitTo: limit">
<td><a href="{{ x.get }}">{{ x.id }}</td>
<td>
<p><b>{{ x.name[0] }}</b></p>
<p><u>Brand</u>: {{ x.Brand }}; <u>Category URL</u>: {{ x.mlnURL }};<u>Price</u>: Rs {{x.Price}} </p>
</td>
<td>
<p><b>{{ x.score }}</b>
</p>
Classifier Score: {{ x.cscore }}
<br>Document Score: {{ x.sscore }}
</td>
</tr>
</table>
</div>
You can do it easily by using existing filter.
<input type="text" ng-model="numberOfRecord" />
Then you can use it in ng-repeat.
<tr ng-repeat="x in data.items | limitTo: numberOfRecord">
People usually use combo box to get the number of records per page and further you can use pagination if you want.
Hope your query resolved :)
What you could do, if you have the user input, is create a new array containing all the number of values you want.
In your controller you could do:
var toShow = data.items.slice(0, size);
And just use the toShow array in your template. Every time the size gets updated, you recalculate the toShow array.
You can use limitTo filter in angularJs
Syntax is{{item | limitTo : limit : begin}}
<td ng-repeat="x in data.items | limitTo : userinput">
you can also specify where the list has to get started by using 'begin' as mentioned above
Try this:
<tr ng-repeat="x in data.items | limitTo: 2">

ngTable dynamic with columns doesn't show column titles

In this plunk I have two tables, one regular ng-table and an ng-table-dynamic with columns. Both point to the same data.
The second table doesn't show column titles, how to fix that?
HTML
<br/> Table 1
<table ng-table="tableParams" class="table table-bordered table-hover">
<tbody>
<tr ng-repeat="u in data" ng-dblclick="alert('double click')">
<td title="'User ID'">{{ u.uid }}</td>
<td title="'Group'">{{ u.ugr }}</td>
</tr>
</tbody>
</table>
<br/> Table 2
<table ng-table-dynamic="tableParams with cols" class="table table-bordered table-hover">
<tr ng-repeat="row in data">
<td title="col.nm" ng-repeat="col in cols">{{row[col.nm]}}</td>
</tr>
</table>
Javascript:
var app = angular.module('app', ['ngTable']);
app.controller('myCtl', function($scope,NgTableParams) {
$scope.cols = [ {nm:'uid'}, {nm:'ugr'} ];
$scope.data = [
{ uid: 'User 1',ugr: 'Group 1'},
{ uid: 'User 2', ugr: 'Group 2'}
];
$scope.tableParams = new NgTableParams({dataset: $scope.data});
});
You're missing the title property within your cols:
$scope.cols = [ {nm:'uid', title: 'User ID'}, {nm:'ugr', title: 'Group ID'} ];
See this plunkr.

AngularJS ng-repeat-start with limitTo doesn't work

I have a list of several objects and at the beginning I want to load just some of them. I took a look at the statement ng-repeat, but I need to have a structure like this:
<table class="table table-hover table-hidden">
<thead>
<tr>
...
</tr>
</thead>
<tbody>
<tr ng-repeat-start="object in objects | filter:query | orderBy:predicate:reverse" ng-init="isCollapsed=true">
...
</tr>
<tr ng-repeat-end class="more">
...
</tr>
</tbody>
</table>
I tried to apply the statement limitTo inside ng-repeat-start, in this way:
<tr ng-repeat-start="object in objects | filter:query | orderBy:predicate:reverse| limitTo: limit" ng-init="isCollapsed=true">
and on controller I wrote:
$scope.limit = 10;
$scope.incrementLimit = function () {
$scope.limit += 10;
};
The function incrementLimit is called by a click on hyperlink
<a href ng-click="incrementLimit()">more</a>
The list of objects is instantiated and filled (with all the elements) when the page loads.
With my approach at the beginnig are loaded and showed first 10 elements correctly, and when I click on "more" the variable $scope.limitis incremented, but on the page nothing happens. Anyone can explain me why?
limitTo is working fine inside ng-repeat-start
Take a look at this
var app = angular.module('myApp', []);
app.controller('Controller', function ($scope) {
$scope.limit = 1;
$scope.incrementLimit = function () {
$scope.limit += 1;
};
$scope.data = [{
title: 'Foo',
text: 'Lorem'
}, {
title: 'Bar',
text: 'Iste'
}, {
title: 'Jon',
text: 'Fat'
}, {
title: 'Los',
text: 'Ice'
}]
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.21/angular.min.js"></script>
<div ng-app='myApp' ng-controller="Controller">
<table border="2" class="table table-hover table-hidden">
<thead>
<tr>...</tr>
</thead>
<tbody>
<tr ng-repeat-start="object in data | filter:query | orderBy:predicate:reverse| limitTo: limit" ng-init="isCollapsed=true" ng-bind="object.title">...</tr>
<tr ng-repeat-end class="more">...</tr>
</tbody>
</table>
more
</div>
Please check the below code and fiddle it is working fine
<body ng-controller="myController">
<button ng-click="incrementLimit()" >increment</button> <br/>
<table class="table table-hover table-hidden">
<thead>
<tr clospan="3">
Head
</tr>
</thead>
<tbody>
<tr ng-repeat-start="friend in objects|limitTo: limit" ng-init="isCollapsed=true">
<td>{{friend.name}}</td>
<td>{{friend.phone}}</td>
<td>{{friend.age}}</td>
</tr>
<tr ng-repeat-end class="more">
<td colspan="3">Footer</td>
</tr>
</tbody>
</table>
</table>
</body>
js code
app = angular.module("app", []);
app.controller("myController", function($scope) {
$scope.objects =
[{
name: 'John',
phone: '555-1212',
age: 10
}, {
name: 'Mary',
phone: '555-9876',
age: 19
}, {
name: 'Mike',
phone: '555-4321',
age: 21
}, {
name: 'Adam',
phone: '555-5678',
age: 35
}, {
name: 'Julie',
phone: '555-8765',
age: 29
}];
$scope.limit = 2;
$scope.incrementLimit = function () {
$scope.limit += 1;
};
});
Fiddle http://jsbin.com/hoguxexuli/1/edit
I solved my problem. Basically I put the hyperlink in a different div, so the controller and the $scope were also different. It was a stupid carelessness.

Categories