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>
Related
I have an issue with this library. First of all, to test the library, I made a simple example work with ul and li tags. It was straightforward. Then, I needed to do a table, and when converting my example to a table it didn't work.
Table is showed but I cannot move any row.
I'm using the cdn way.
I think is something what I missing.
html
<div id='app-example-drag' >
<table class="table table-striped">
<thead class="thead-dark">
<tr>
<th scope="col">Id</th>
<th scope="col">Name</th>
<th scope="col">Sport</th>
</tr>
</thead>
<draggable v-model="list" tag="tbody">
<tr v-for="item in list" :key="item.name">
<td scope="row">{{ item.id }}</td>
<td>{{ item.name }}</td>
<td>{{ item.sport }}</td>
</tr>
</draggable>
</table>
</div>
js
Vue.component('draggable',vuedraggable);
applicationExample = new Vue({
el: '#app-example-drag',
display: "Table",
order: 8,
data() {
return {
list: [
{ id: 1, name: "Abby", sport: "basket" },
{ id: 2, name: "Brooke", sport: "foot" },
{ id: 3, name: "Courtenay", sport: "volley" },
{ id: 4, name: "David", sport: "rugby" }
]
};
}
});
https://jsfiddle.net/0Luhd694/3/
Thanks in advance
I just ran into this same problem. I think it has something to with recent version. Replace the draggable element with a tbody and make is='draggable'.
<div id='app-example-drag' >
<table class='table'>
<thead>
<tr><th scope='col'>description</th></tr>
</thead>
<tbody tag='tbody' v-model='lista1' is='draggable' group='items'>
<tr v-for='item in lista1' :key='item.id'>
<td scope='row'>{{item.description}}</td>
</tr>
</tbody>
</table>
</div>
https://jsfiddle.net/oqf64kdx/
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>
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/
I am a newbie to Angular JS.
I have been trying iterate through a model collection and display the same in a table.
The Model looks like :
var myModule = angular
.module("myModule", [])
.controller("myController", function ($scope) {
var countries = [
{
name: "UK",
cities: [
{name: "London"},
{name: "Birmingham" },
{name: "Manchestar" }
],
flag:"/Images/UK.gif"
},
{
name: "USA",
cities: [
{name: "Los Angeles"},
{name: "Houston"},
{name: "Florida"},
],
flag:"/Images/USA.png"
}
];
$scope.countries = countries;
});
And I want the table structure to be
Country City1 City2 City3 Flag
UK London Birmingham Manchestar .....
USA ...... ......... ......... .....
But I could not do the same in the html page.
So far the code looks like :
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" ng-app="myModule">
<head>
<title></title>
<script src="Scripts/angular.js"></script>
<script src="Scripts/MyModuleScript.js"></script>
</head>
<body ng-controller="myController">
<div>
<table>
<thead>
<tr>
<th>Country</th>
<th>City 1</th>
<th>City 2</th>
<th>City 3</th>
<th>Flag</th>
</tr>
</thead>
<tbody ng-repeat="country in countries">
<tr ng-repeat="city in country.cities">
<td>{{ country.name }}</td>
<td>
{{......}}
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
What I need to do to achieve the same ? Please explain.
try this. you must put ng-repeat on td instead of row.
var myModule = angular
.module("myModule", [])
.controller("myController", function ($scope) {
$scope.countries = [
{
name: "UK",
cities: [
{name: "London"},
{name: "Birmingham" },
{name: "Manchestar" }
],
flag:"/Images/UK.gif"
},
{
name: "USA",
cities: [
{name: "Los Angeles"},
{name: "Houston"},
{name: "Florida"},
],
flag:"/Images/USA.png"
}
];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myModule" ng-controller="myController">
<div>
<table>
<thead>
<tr>
<th>Country</th>
<th>City 1</th>
<th>City 2</th>
<th>City 3</th>
<th>Flag</th>
</tr>
</thead>
<tbody ng-repeat="country in countries">
<tr>
<td>{{ country.name }}</td>
<td ng-repeat="city in country.cities">
{{city.name}}
</td>
<td><img ng-src="{{country.flag}}"></td>
</tr>
</tbody>
</table>
</div>
</div>
repeat a little and it works as you need it.
<tbody ng-repeat="country in countries">
<tr >
<td >{{ country.name }}</td>
<td ng-repeat="city in country.cities">
{{city.name}}
</td>
<td><img ng-src="{{country.flag}}"></td>
</tr>
</tbody>
var myModule = angular
.module("myModule", [])
.controller("myController", function ($scope) {
var countries = [
{
name: "UK",
cities: [
{name: "London"},
{name: "Birmingham" },
{name: "Manchestar" }
],
flag:"/Images/UK.gif"
},
{
name: "USA",
cities: [
{name: "Los Angeles"},
{name: "Houston"},
{name: "Florida"},
],
flag:"/Images/USA.png"
}
];
$scope.countries = countries;
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" ng-app="myModule">
<head>
<title></title>
<script src="Scripts/angular.js"></script>
</head>
<body ng-controller="myController">
<div>
<table>
<thead>
<tr>
<th>Country</th>
<th>City 1</th>
<th>City 2</th>
<th>City 3</th>
<th>Flag</th>
</tr>
</thead>
<tbody ng-repeat="country in countries">
<tr >
<td >{{ country.name }}</td>
<td ng-repeat="city in country.cities">
{{city.name}}
</td>
<td><img ng-src="{{country.flag}}"></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
var myModule = angular
.module("myModule", [])
.controller("myController", function ($scope) {
var countries = [
{
name: "UK",
cities: [
{name: "London"},
{name: "Birmingham" },
{name: "Manchestar" }
],
flag:"/Images/UK.gif"
},
{
name: "USA",
cities: [
{name: "Los Angeles"},
{name: "Houston"},
{name: "Florida"},
],
flag:"/Images/USA.png"
}
];
$scope.countries = countries;
});
Everything is fine except your HTML.
Your first ng-repeat for countries should be for <tr>
The second one should be for <td>
tbody is not supposed to be repeated as seen by some of the answers here. As per w3c HTML5 Specs tbody tbody is single element after thead
You are on the right track just remember that ng-repeat will repeat the element on which it is specified as attribute.
<tbody>
<tr ng-repeat="country in countries">
<td >{{ country.name }}</td>
<td ng-repeat="city in country.cities">
{{city.name}}
</td>
<td><img ng-src="{{country.flag}}"></td>
</tr>
</tbody>
Here's the data I'm working with:
$scope.products = [
{
'id': 643,
'name': 'Product Name',
'applications': [
{
'id': 100,
'name': 'Adobe After Effects CC (2014)',
'gfx': [
{
'id': 514,
'name': 'Graphics AE Test 1'
}
]
},
{
'id': 101,
'name': 'Adobe Premiere Pro CC (2014)',
'gfx': [
{
'id': 514,
'name': 'Graphics AP Test 1'
},
{
'id': 512,
'name': 'Graphics AP Test 2'
}
]
}
]
}
];
What i'm trying to do is loop through all of the graphics card for a specific application. You choose the application via a dropdown, and I have the selected application in a variable {{ scope.selectedApplication }}. So with that, here's what I have tried:
<tr data-ng-repeat="driver in result.applications | filter: { name: selectedApplication } track by $index">
<td>{{ driver.gfx[$index].name }}</td>
</tr>
So this is somewhat working, just not exactly how I want. The filter is filtering it down to the correct application, which works fine. The problem I am having is that driver.gfx[$index].name is only showing the first result. Since I am looping through applications instead of gfx, the $index isn't going to work for me.
How can I loop through the graphics cards after my initial ng-repeat? It seems like I need two statements, but how would that work?
Am I going about this the wrong way?
you can have nested hg-repeat if you like to have a nested table.
<tr data-ng-repeat="driver in result.applications | filter: { name: selectedApplication } track by $index">
<td>
<table>
<tr ng-repeat="item in driver.gfx">
<td >
{{item.name}}
<td/>
</tr>
</table>
</td>
</tr>
if you want to have single denormalized table, one option would be to create a function that does the denormalization and then use result of that function in a normal hg-repeat.
The other option would be having multiple tbody. so your outer loop occurs on tbody and inner loop on row
<tbody data-ng-repeat="driver in result.applications | filter: { name: selectedApplication } track by $index">
<tr ng-repeat="item in driver.gfx">
<td >
{{item.name}}
<td/>
</tr>
</tbody>
and finally you can have some rows that either style them as separators or just hide them by CSS and use ng-repeat-start and hg-repeat-end like this
<table>
<tr class="separator" data-ng-repeat-start="driver in result.applications | filter: { name: selectedApplication } track by $index"><td></td></tr>
<tr ng-repeat="item in driver.gfx">
<td >
{{item.name}}
<td/>
</tr>
<tr class="seperator" ng-repeat-end><td></td></tr>
</table>
You need another ng-repeat that loops through each gfx.
<td>
<ul>
<li ng-repeat="gfx in driver.gfx">{{ gfx.name }}</li>
</ul>
</td>
Assuming the selected application is set via a binding of {{ selectedApplication }} ($scope is implied), then your ng-repeat should look like:
<tr data-ng-repeat="driver in selectedApplication | filter: { name: selectedApplication } track by $index">
<td>{{ driver.gfx[$index].name }}</td>
</tr>
This means you'll be talking about the driver inside the selected application object.