AngularJS nested ng-repeat in table - javascript

I am new to AngularJs and have come across an issue with Json data with nested arrays.
I have simplified the code to a simple html doc, this can be found below.
The first property {{HelloMessage}} is working and gets populated with the string value stored in the property HelloMessage, but the ng-repeat is not.
After looking online, I discovered that I in fact had an array within an array, so assumed that I needed to have an ng-repeat within an ng-repeat, but it is not working. I am quite sure that it is something simple that I have done wrong.
<!DOCTYPE html>
<html ng-app="app">
<head>
<title></title>
</head>
<body>
<h1 ng-controller="myController">{{helloMessage}}</h1>
<div>
<table>
<thead>
<tr>
<th>Id</th>
<th>UserId</th>
<th>DisplayName</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="stream in Data.Records">
<tr ng-repeat="record in stream.Users">
<td>{{stream.Id}}</td>
<td>{{stream.User}}</td>
<td>
{{stream.Description}}
</td>
<!--<td>
<table>
<tbody>
<tr ng-repeat="b in value">
<td>{{b.user}}</td>
</tr>
</tbody>
</table>
</td>-->
</tr>
</tr>
</tbody>
</table>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script type="text/javascript">
angular.module('app', []).controller('myController',
function ($scope) {
$scope.helloMessage = "Hi";
$scope.Data = [{
Success: true,
ErrorMessage: null,
SuccessMessage: null,
Records: [{
"CreatedBy": "Mickey Mouse",
"CreatedDate": "2015-08-17T13:16:22.713",
"CreatedDateDisplay": "17-08-2015",
"Description": "Test 1",
"Id": 7546798576985769857,
"Name": "Test 1",
"UpdatedBy": "",
"UpdatedDate": null,
"UpdatedDateDisplay": null,
"User": null,
"UserId": 0,
"Users": [{
"Users": [{
"Id": 7546798576985769858,
"UserId": 7546798576985769857,
"DisplayName": "Daffy Duck"
}, {
"Id": 7546798576985769859,
"UserId": 7546798576985769857,
"DisplayName": "Pluto"
}
],
"User": "Bugs Bunny",
"UserId": 7546798576985769857,
"Name": "Test 2",
"Description": "Test 2",
"Id": 7546798576985769857,
"CreatedBy": "Goofy",
"CreatedDate": "2015-08-25T14:03:28.083",
"UpdatedBy": "Porky Pig",
"UpdatedDate": "2017-03-27T08:19:36.077",
"CreatedDateDisplay": "25-08-2015",
"UpdatedDateDisplay": "27-03-2017"
}
]
}
]
}
];
});
</script>
</body>
</html>
No errors are throw in Chrome Console

Rewrite the ng-repeat as
<tr ng-repeat="stream in Data[0].Records[0].Users[0].Users">
</tr>
Use
<td>{{stream.Id}}</td>
<td>{{stream.UserId}}</td>
<td>{{stream.DisplayName}}</td>
instead of
<td>{{stream.Id}}</td>
<td>{{stream.User}}</td>
<td>{{stream.Description}}</td>
function myController($scope) {
$scope.helloMessage = "Hi";
$scope.Data = [{
Success: true,
ErrorMessage: null,
SuccessMessage: null,
Records: [{
"CreatedBy": "Mickey Mouse",
"CreatedDate": "2015-08-17T13:16:22.713",
"CreatedDateDisplay": "17-08-2015",
"Description": "Test 1",
"Id": 7546798576985769857,
"Name": "Test 1",
"UpdatedBy": "",
"UpdatedDate": null,
"UpdatedDateDisplay": null,
"User": null,
"UserId": 0,
"Users": [{
"Users": [{
"Id": 7546798576985769858,
"UserId": 7546798576985769857,
"DisplayName": "Daffy Duck"
}, {
"Id": 7546798576985769859,
"UserId": 7546798576985769857,
"DisplayName": "Pluto"
}],
"User": "Bugs Bunny",
"UserId": 7546798576985769857,
"Name": "Test 2",
"Description": "Test 2",
"Id": 7546798576985769857,
"CreatedBy": "Goofy",
"CreatedDate": "2015-08-25T14:03:28.083",
"UpdatedBy": "Porky Pig",
"UpdatedDate": "2017-03-27T08:19:36.077",
"CreatedDateDisplay": "25-08-2015",
"UpdatedDateDisplay": "27-03-2017"
}]
}]
}];
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.min.js"></script>
<div ng-app>
<div ng-controller="myController">
<h1>{{helloMessage}}</h1>
<table>
<thead>
<tr>
<th>Id</th>
<th>UserId</th>
<th>DisplayName</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="stream in Data[0].Records[0].Users[0].Users">
<td>{{stream.Id}}</td>
<td>{{stream.UserId}}</td>
<td>
{{stream.DisplayName}}
</td>
</tr>
</tbody>
</table>
</div>
</div>

First you have to define your controller to body level as following.
<body ng-controller="myController">
You have defined it as h1 level so it is not accessible.
I have made changes in your code please as following.
<!DOCTYPE html>
<html ng-app="app">
<head>
<title></title
</head>
<body ng-controller="myController">
<h1>{{helloMessage}}</h1>
<div>
<table>
<thead>
<tr>
<th>Id</th>
<th>UserId</th>
<th>DisplayName</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="stream in Data[0].Records[0].Users[0].Users">
<td>{{stream.Id}}</td>
<td>{{stream.UserId}}</td>
<td>{{stream.DisplayName}}
</td>
</tr>
</tbody>
</table>
</div>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script type="text/javascript">
angular.module('app', []).controller('myController',
function ($scope) {
$scope.helloMessage = "Hi";
$scope.Data = [{
Success: true,
ErrorMessage: null,
SuccessMessage: null,
Records: [{
"CreatedBy": "Mickey Mouse",
"CreatedDate": "2015-08-17T13:16:22.713",
"CreatedDateDisplay": "17-08-2015",
"Description": "Test 1",
"Id": 7546798576985769857,
"Name": "Test 1",
"UpdatedBy": "",
"UpdatedDate": null,
"UpdatedDateDisplay": null,
"User": null,
"UserId": 0,
"Users": [{
"Users": [{
"Id": 7546798576985769858,
"UserId": 7546798576985769857,
"DisplayName": "Daffy Duck"
}, {
"Id": 7546798576985769859,
"UserId": 7546798576985769857,
"DisplayName": "Pluto"
}],
"User": "Bugs Bunny",
"UserId": 7546798576985769857,
"Name": "Test 2",
"Description": "Test 2",
"Id": 7546798576985769857,
"CreatedBy": "Goofy",
"CreatedDate": "2015-08-25T14:03:28.083",
"UpdatedBy": "Porky Pig",
"UpdatedDate": "2017-03-27T08:19:36.077",
"CreatedDateDisplay": "25-08-2015",
"UpdatedDateDisplay": "27-03-2017"
}]
}]
}];
});
</script>
</html>
Hope this will help you.
thanks

Thank you, thank you all for your help. I have used Geethu Jose answer, but it still did not give me exactly what I was looking for, but after much head scratching I did come up with a solution for my problem. Instead of using the array placeholders [0] I needed access the arrays themselves at the different levels, so I had to change the code to the following.
<div ng-app>
<div ng-controller="myController">
<h1>{{helloMessage}}</h1>
<table>
<tbody>
<tr ng-repeat="data in Data">
<td>
<table ng-repeat="records in data">
<thead>
<tr>
<th>UserId</th>
<th>User</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{records.UserId}}</td>
<td>{{records.User}}</td>
<td>{{records.Name}}</td>
<td>
<table>
<thead>
<tr>
<th>Id</th>
<th>UserId</th>
<th>DisplayName</th>
</tr>
</thead>
<tr ng-repeat="streamUser in records.Users">
<td>{{streamUser.Id}}</td>
<td>{{streamUser.UserId}}</td>
<td>{{streamUser.DisplayName}}</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>

It seems that your JSON is full of arrays. It could probably be improved, but there is how you can display it in its current state. You don't need to nest ng-repeat:
<tbody>
<tr ng-repeat="user in Data[0].Records[0].Users[0].Users">
<td>{{user.Id}}</td>
...
</tbody>
Working JSFiddle of your code

Related

Jsreport how to fill the table with data

im trying to to fill a table with data to export it in pdf using jsreport
but i couldnt manage to do it .
This is the html file :
<h1>test{{test}}</h1>
<table class='table striped'>
<thead>
<tr>
<th>OrderID</th>
<th>ShipAddress</th>
<th>ShipCity</th>
<th>ShipCountry</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{items.order}}</td>
<td>{{items.addr}}</td>
<td>{{items.city}}</td>
<td>{{items.country}}</td>
</tr>
</tbody>
</table>
And this is the data :
{
"items": [
{
"order": "65854",
"addr": "test 1",
"city": "2fc2",
"country": "2fc2"
},
{
"order": "75757",
"addr": "azerty",
"city": "2fc2",
"country": "2fc2"
},
{
"order": "65575784",
"addr": "tst",
"city": "2fc2",
"country": "2fc2"
}
]
}
I've tried a lot of things but i couldnt manage to do it.
you must use
<h1>test{{test}}</h1>
<table class='table striped'>
<thead>
<tr>
<th>OrderID</th>
<th>ShipAddress</th>
<th>ShipCity</th>
<th>ShipCountry</th>
</tr>
</thead>
<tbody>
{{#each items}}
<tr>
<td>{{order}}</td>
<td>{{addr}}</td>
<td>{{city}}</td>
<td>{{country}}</td>
</tr>
{{/each}}
</tbody>
</table>
https://jsreport.net/learn/handlebars

How to code a nested v-for loop to display all elements?

I am coding an app which makes orders and for each order their are a certain amount of products within them. How would i code my VueJs code below to display all products for each order that comes in? The code below is my VueJS template
<div class="card card-default" v-for="(order, index) in orders">
<p style="padding:0px;"><strong> User: </strong> {{order.user.name}} </p>
<table class="table-repsonsive table-bordered ">
<thead>
<th scope="col">Product</th>
<th scope="col">Price</th>
<th scope="col">Quantity</th>
</thead>
<tbody v-for="(product, pindex) in orders">
--how to loop through each product of each order in the array?
<td>{{product.order[pindex].name}}</td>
<td>R{{product.order[pindex].price}}</td>
<td>{{product.order[pindex].quant}}</td>
</tbody>
</table>
</div>
This is the order object that is pushed within the orders array after each order takes place
{
"order": [
{
"id": 1,
"name": "Garden",
"price": 20,
"quant": 1
},
{
"id": 2,
"name": "Greek",
"price": 24,
"quant": 1
},
{
"id": 3,
"name": "Chicken mayo",
"price": 24,
"quant": 1
}
],
"user": {
"id": 1,
"role_id": 2,
"name": "Mapia",
"email": "mapia#gmail.com",
"avatar": "users/default.png",
"settings": null,
"created_at": "2018-07-05 13:10:26",
"updated_at": "2018-07-05 13:10:26"
}
}
You should take you order and loop through its property order
<tbody v-for="product in order.order">
<td>{{product.name}}</td>
<td>R{{product.price}}</td>
<td>{{product.quant}}</td>
</tbody>

How to dynamically loop all values in a json string

I'm creating a project in Vue.js
I need to loop through a JSON object but can't find out how to access this.
what I got:
"functionality": {
"uitgifte": {
"image": "",
"value": "Handmatige capsule inname en uitgifte",
"label": "",
"splash": true,
"compare": false
},
"schakelaar": {
"image": "",
"value": "Automatische en programmeerbare aan/uit schakelaar",
"label": "",
"splash": true,
"compare": false
},
"kopjesrooster": {
"image": "",
"value": "Draaibaar kopjesrooster voor latte macchiato-glazen",
"label": "",
"splash": true,
"compare": false
},
"ontkalking": {
"image": "",
"value": "Automatische melding voor ontkalking",
"label": "",
"splash": true,
"compare": false
},
"kopgroottes": {
"image": "",
"value": "Programmeerbare kopgroottes",
"label": "",
"splash": true,
"compare": false
}
},
and the html:
<div class="tab">
<table>
<tbody>
<tr>
<td>{{ main.pageCopy.functionele_specificaties }}</td>
</tr>
<tr>
<td v-for="functionality in machine.functionality.uitgifte.value" :key="functionality">{{ machine.functionality.uitgifte.value }}</td>
<td>
<img src="" alt="">
</td>
</tr>
</tbody>
</table>
</div>
The part that says machine.functionality.uitgifte.value I need the "uitgifte" part to be dynamic so it loops through all the elements like it in the JSON. So "uitgifte, schakelaar, kopjesrooster" etc.
Would be awesome if anyone knows the trick.
Thanks.
You simply start your for loop at a higher object level:
<div class="tab">
<table>
<tbody>
<tr>
<td>{{ main.pageCopy.functionele_specificaties }}</td>
</tr>
<tr>
<td v-for="(functionality, index) in machine.functionality" :key="index">
{{ functionality.value }}</td>
<td>
<img src="" alt="">
</td>
</tr>
</tbody>
</table>
</div>
BTW: If you have control of the datasource, make sure to provide an ID for each object and use that ID as the key of the v-for loop.

How to keep matched row on top of other rows in table using angularjs?

I'm using Smart table i want to keep matched rows on top of other rows in table using angularjs(1), in my case i have been matching string from table column, on the basis of matched string I'm changing row background color, but i want to show those colored rows on top of the other rows, so that I'm able see matched rows instantly.
it is worked if i sort like below, but it affect only current page, i want display all matched rows to top of other rows irrespective pagination and all.
<tr ng-repeat="emp in employees | orderBy:set_color" ng-style="set_color(emp)">
how i can achieve this. if you want more info please take a look at this link
var myApp = angular.module('myApp', [])
.controller('employeeController', function ($scope) {
var employees = [{
"Name": "Alfreds Futterkiste",
"City": "Berlin",
"Country": "Germany"
}, {
"Name": "Berglunds snabbköp",
"City": "Luleå",
"Country": "Sweden"
}, {
"Name": "Blauer See Delikatessen",
"City": "Mannheim",
"Country": "Germany"
}, {
"Name": "Blondel père et fils",
"City": "Strasbourg",
"Country": "France"
}, {
"Name": "Bólido Comidas preparadas",
"City": "Madrid",
"Country": "Spain"
}, {
"Name": "Bon app'",
"City": "Marseille",
"Country": "France"
}, {
"Name": "Bottom-Dollar Marketse",
"City": "Tsawassen",
"Country": "Canada"
}, {
"Name": "Cactus Comidas para llevar",
"City": "Buenos Aires",
"Country": "Argentina"
}, {
"Name": "Centro comercial Moctezuma",
"City": "México D.F.",
"Country": "Mexico"
}, {
"Name": "Chop-suey Chinese",
"City": "Bern",
"Country": "Switzerland"
}, {
"Name": "Comércio Mineiro",
"City": "São Paulo",
"Country": "Brazil"
}];
$scope.employees=employees;
$scope.set_color = function (emp) {
var inputString = emp.Country;
for (i = 0; i < inputString.length; i++) {
var findme = "France";
if (inputString.indexOf(findme) > -1) {
return { 'background-color': '#FFCCCB' }
}
}
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.min.js"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<body ng-app="myApp">
<div ng-controller="employeeController">
<div class="container" style="margin-top:40px;">
<div class="row">
{{error}}
<div class="col-md-6">
<table class="table table-bordered table-condensed">
<thead>
<tr>
<th>Name</th>
<th>City</th>
<th>Country</th>
</tr>
</thead>
<tbody >
<tr ng-repeat="emp in employees" ng-style="set_color(emp)">
<td>{{emp.Name}}</td>
<td>{{emp.City}}</td>
<td>{{emp.Country}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</body>
Thank you
With AngularJS i believe I would choose this option:
HTML
orderBy can take multiple filters
<tr ng-repeat="emp in employees | orderBy: [sort, 'Name']"
ng-class="{'matched': emp.matched }">
JS
var findme = "France";
$scope.sort = (emp) => {
emp.matched = emp.Country.indexOf(findme) > -1;
return !emp.matched;
}
See working fiddle:
https://jsfiddle.net/kraaness/vft90229/
You could treat the std as a list, and sorting it taking into account the similarities. For example you could do the following:
// This function will return a list with the matching elements first,
// and the non matching after.
$ordered = function(findme) {
var values = Object.values(std);
var matching = values.filter(e => e === findme);
var notMatching = values.filter(e => e !== findme);
return matching.concat(notMatching);
}
And then in the html you could do the following:
<tbody>
<tr ng-repeat="std in students" ng-style="set_color(std)">
<td ng-repeat="x in ordered()">{{x}}</td>
</tr>
</tbody>
I'm more familiar with angular 2, 4 and 5, so forget me if calling a function within the ng-repeat is not allowed. Other solution would be to store that list as a variable.
Hope it helps.
You can do it like this:
HTML
// I used `B` as `std.Name` for example in my code:
function matchRowByName() {
$.each($('tr[ng-repeat="std in students"'), function() {
if ($(this).find('td').first().text() === "B") {
$('table').prepend($(this));
$(this).addClass('matched');
}
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr ng-repeat="std in students" ng-style="set_color(std)">
<td>A</td>
<td>a#test.com</td>
</tr>
<tr ng-repeat="std in students" ng-style="set_color(std)">
<td>B</td>
<td>b#test.com</td>
</tr>
<tr ng-repeat="std in students" ng-style="set_color(std)">
<td>C</td>
<td>c#test.com</td>
</tr>
</table>
Online demo(jsFiddle)

Ng-click and ng-show AngularJS

I have a list of dictionaries, and I want to toggle show all the students and their details for each classroom.
This is the HTML:
<div ng-app="myApp" ng-controller="myCtrl">
<div class="classrooms-details" ng-show="Students">
<table class="table table-striped">
<thead>
<tr>
<th>First name</th>
<th>Last name</th>
<th>Gender</th>
<th>Birthday</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="classroom in classrooms">
<td>{{classroom.student.first_name}}</a></td>
<td>{{classroom.student.last_name}}</td>
<td>{{classroom.student.gender}}</td>
<td>{{classroom.student.birthday}}</td>
</tr>
</tbody>
</table>
</div>
<table class="table table-striped">
<thead>
<tr>
<th>Classroom</th>
<th>School</th>
<th>Academic year</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="classroom in classrooms">
<td>{{classroom.classroom}}</td>
<td>{{classroom.school.school_name}}</td>
<td>{{classroom.academic_year}}</td>
</tr>
</tbody>
</table>
</div>
I've tried to use ng-click/ng-show, but it's not working.
And this is the script:
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.classrooms = [{
"school": {
"id": 1,
"school_name": "IPSIA F. Lampertico",
"address": "Viale Giangiorgio Trissino, 30",
"city": "Vicenza"
},
"academic_year": "2015/2016",
"classroom": "1^A",
"floor": 0,
"students": [{
"classroom": 1,
"first_name": "Stefano",
"last_name": "Rossi",
"gender": "M",
"birthday": "1998-06-22"
}, {
"classroom": 1,
"first_name": "Luca",
"last_name": "Possanzini",
"gender": "M",
"birthday": "1999-11-22"
}]
}, {
"school": {
"id": 2,
"school_name": "ITIS A. Rossi",
"address": "Via Legione Gallieno, 52",
"city": "Vicenza"
},
"academic_year": "2015/2016",
"classroom": "2^B",
"floor": 0,
"students": [{
"classroom": 2,
"first_name": "Sergio",
"last_name": "Lazzari",
"gender": "M",
"birthday": "2001-01-29"
}]
}];
console.log($scope.classrooms);
});
I don't know how to access "students" values, and I'd like the students details to be shown only when clicking on the classroom name.
How could I accomplish this?
You just need to set a specific classroom as the "active" classroom and display the students within. The easiest way to do this would be something like:
View
<tr ng-if="activeClassroom" ng-repeat="student in activeClassroom.students">
<td>{{student.first_name}}</a></td>
<td>{{student.last_name}}</td>
<td>{{student.gender}}</td>
<td>{{student.birthday}}</td>
</tr>
...
<tr ng-repeat="classroom in classrooms">
<td>{{classroom.classroom}}</td>
<td>{{classroom.school.school_name}}</td>
<td>{{classroom.academic_year}}</td>
</tr>
Controller
$scope.activeClassroom = null;
$scope.setActiveClassroom = function (classroom) {
$scope.activeClassroom = classroom;
};

Categories