Dynamically create HTML table rows from object using angular ng-repeat - html

FWIW the HTML angular code is being used in Node-RED in a "template" node.
I have an object composed of circuit boards identified by serial numbers. Each circuit board has two channels that each have their own outputs.
These numbers may change though, for example, some circuit boards in the future will have more channels or I will add another circuit board to the system. So I need the table to be created presumably using nested loops to traverse the message object and pull out whatever information is there at the time.
I successfully used ng-repeat to build individual tables for each circuit board by ng-repeating over the channels of each board. But I would prefer if I had one master table of every single circuit board with every channel so that I can sort that table based on the status of setpoint value for example.
Here is my object:
{ "serialNum": {
"1a": {
"channel": {
"0": {
"status": "running",
"value" : 100.0,
"setpoint": 200.0
},
"1": {
"status": "running",
"value" : 100.1,
"setpoint": 200.1
}
}
},
"2a": {
"channel": {
"0": {
"status": "running",
"value" : 200.0,
"setpoint": 300.0
},
"1": {
"status": "running",
"value" : 200.1,
"setpoint": 300.1
}
}
},
"3a": {
"channel": {
"0": {
"status": "stopped",
"value" : 300.0,
"setpoint": 400.0
},
"1": {
"status": "stopped",
"value" : 300.1,
"setpoint": 400.1
}
}
}
}
}
And here is code I am currently trying (I'm guessing I'm doing a LOT of things wrong here...):
<!DOCTYPE html>
<html>
<style>
table, th , td {
border: 1px solid grey;
border-collapse: collapse;
padding: 5px;
}
table tr:nth-child(odd) {
background-color: #f1f1f1;
}
table tr:nth-child(even) {
background-color: #ffffff;
}
</style>
<table id="board status" border="1" width = 1000px height = 400px>
<thead>
<tr>
<th>Serial #</th>
<th>Channel #</th>
<th>Status</th>
<th>Value</th>
<th>Setpoint</th>
</tr>
</thead>
<tbody ng-repeat="serial in msg.boardMsg.serialNum">
<tr ng-repeat="channelNum in msg.boardMsg.serialNum[serial].channel">
<td> {{serial}} </td>
<td>{{channelNum}}</td>
<td ng-style = "{color : msg.boardMsg.serialNum[serial].channel[channelNum].status === 'stopped' ? 'red' : 'green'}">
{{msg.boardMsg.serialNum[serial].channel[channelNum].status == "stopped" ? "stopped" : "running"}}
</td>
<td>{{msg.boardMsg.serialNum[serial].channel[channelNum].value</td>
<td>{{msg.boardMsg.serialNum[serial].channel[channelNum].setpoint</td>
</tr>
</tbody>
</table>
I want the table to look like this:
So far my code only gives me the header. Thanks in advance for the help!

Use the (key, value) form of the ng-repeat directive:
<tbody ng-repeat="(serialNum, serialVal) in msg.boardMsg.serialNum">
<tr ng-repeat="(channelNum, channelVal) in serialVal.channel">
<td> {{serialNum}} </td>
<td>{{channelNum}}</td>
<td ng-style = "{color : channelVal.status === 'stopped' ? 'red' : 'green'}">
{{channelVal.status == "stopped" ? "stopped" : "running"}}
</td>
<td>{{channelVal.value}}</td>
<td>{{channelVal.setpoint}}</td>
</tr>
</tbody>
For more information, see
AngularJS ng-repeat Directive API Reference - Iterating Over Object Properties

Related

How do I display data from JSON into a table in Reactjs

I have JSON structure like below:
const villages =
{
"lossesOccured":
[
{
"type": "destroyed",
"affectedOn": "humans",
"quantity": 120,
"reliefFund": 100000,
"location": {
"district": "thanjavur",
"villageName": "madukkur",
"pincode": "614903"
}
},
{
"type": "physicalDamage",
"affectedOn": "humans",
"quantity": 250,
"reliefFund": 50000,
"location": {
"district": "thanjavur",
"villageName": "madukkur",
"pincode": "614903"
}
},
]
}
I need help in displaying the JSON data in the form of table like below Using React. Also, need the table row to be added automatically whenever a new element is added in JSON.
<table>
<thead>
<tr>
<th>AffectedOn</th>
<th>Type</th>
<th>Quantity</th>
</tr>
</thead>
<tbody>
{
villages.lossesOccured.map(loss => (
<tr>
<td>{loss.affectedOn}</td>
<td>{loss.type}</td>
<td>{loss.quantity}</td>
</tr>
)
}
</tbody>
</table>

Get DataTables to output an array of objects in appropriate columns

I'm working on a chemicals database web application. Using DataTables 1.10.16 and CakePHP 3.5
Cake is producing a JSON feed. A sample is below:
[
{
"id": 1,
"app_id": "ID000001",
"name": "Chromium",
"ecs": [
{
"id": 1,
"value": "123-456-7"
},
{
"id": 32,
"value": "222-333-444"
},
],
"cas": [
{
"id": 1,
"value": "987-654-3"
}
]
},
]
For certain chemicals there are multiple EC (ecs in the JSON) and CAS Numbers (cas in the JSON).
I don't know if/how it's possible to get DataTables to loop through these objects, outputting them in the appropriate columns, with a separator such as a <br> tag.
My table markup looks like this:
<table id="substancesTable" class="table responsive display table-striped" cellspacing="0" width="100%">
<thead>
<tr>
<th>Application ID</th>
<th>EC Number</th>
<th>CAS Number</th>
<th>Chemical Name</th>
</tr>
</thead>
</table>
And in my Javascript I'm doing this:
$('#substancesTable').DataTable({
"processing": true,
"serverSide": true,
"searching": false,
"ajax": {
"url" : "/get-substances.json",
"method" : "POST",
"dataSrc":""
},
"columns": [
{ "data": "app_id", "name" : "app_id" },
{ "data": "ecs", "name" : "ec_number" },
{ "data": "cas", "name" : "cas_number" },
{ "data": "name", "name" : "name" },
]
});
This works in terms of populating the "Application ID" and "Chemical Name" columns - but that's because there is a simple 1:1 mapping in the JSON (no arrays/objects).
The output for the "EC Number" and "CAS Number" columns is just [object Object] and is repeated the number of objects there are. In the example above there are 2 EC Numbers for this chemical so the output under "EC Number" is [object Object],[object Object]
Can anyone assist with this? I'd like the output to be generated by looping through my JSON and introducing a break between each item, e.g.
123-456-7<br>222-333-444
You'll be needing a render function like this:
{
"data": "ecs",
"name": "ec_number",
"title":"EC Number",
"render": function(d,t,r){
return d.map(function(e) {
return e.value;
}).join("<br/>");
}
}
Working JSFiddle here.

Nested rows in Angular Table

I have a JSON array like this:
[
{
"students": {
"Student1": {
"number": "15",
"books": {
"Mystery": [
"Book1",
"Book2"
]
}
},
"Student2": {
"number": "12",
"books": {
"Romance": [
"Book1"
],
"Adventure": [
"Book1",
"Book2"
]
}
},
"Student3": {
"number": "116",
"books": {
}
}
},
"class": "7th Grade",
"school": "High School 1"
}
]
I want to display this data as a table on an Angular1 page in the following manner:
How can I make it so that the columns resize with each other, and how can I have nested ng-repeats as needed?
I tried to have nested tables inside the student, student-number, and books columns, and a table within the table in the books column, but the alignment was always off, and I couldn't get a default value of "No Books" to show up if the "books" field was empty.
Here's a Plunkr of what I've tried so far.
One of possible solutions is to combine several tables(based on $scope.base, $scope.students, $scope.books arrays, that calculated in controller) into one virtual, desired table via float:left(to ensure they located in one row). Docking of rows is provided by setting of their style:height, which depends on number of their children. Direct solution will be very complicated due to complicated html markup of table with rowspan attributes. Also I added second item(items.push(items[0])), to demonstrate, that solution works at case of several items.
angular.module('app', [])
.controller('MyController', ['$scope', function($scope) {
var items = [
{
"students": {
"Student1": {
"number": "15",
"books": {
"Mystery": [
"Book1",
"Book2"
]
}
},
"Student2": {
"number": "12",
"books": {
"Romance": [
"Book1"
],
"Adventure": [
"Book1",
"Book2"
]
}
},
"Student3": {
"number": "116",
"books": {
}
},
"class": "7th Grade",
"school": "High School 1"
}
}
];
items.push(items[0]);
$scope.base = [];
$scope.students = [];
$scope.books = [];
for(var item of items){
var temp = $scope.books.length;
for(var student in item.students){
if(['class', 'school'].indexOf(student) == -1){
var studentV = item.students[student];
$scope.students.push({name:student, number: studentV.number, w: Object.keys(studentV.books).length || 1});
for(var book in studentV.books)
$scope.books.push((book + ':' + JSON.stringify(studentV.books[book])).replace(/"/g, ''));
if(Object.keys(studentV.books).length == 0)
$scope.books.push('No books');
}
}
$scope.base.push({cl: item.students.class, school: item.students.school, w: $scope.books.length - temp});
}
}]);
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
table.left, table.left th, table.left td {
border-right: 0px
}
tr {
text-align:center
}
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
<div ng-app='app' ng-controller="MyController">
<table style='float:left;border-right:0' class='left'>
<thead>
<tr>
<th>School</th>
<th>Class</th>
</tr>
</thead>
<tbody>
<tr ng-repeat='item in base' style='height:{{item.w*30}}px'>
<td>{{item.school}}</td>
<td>{{item.cl}}</td>
</tr>
</tbody>
</table>
<table style='float:left' class='left'>
<thead>
<tr>
<th>Student</th>
<th>Student-number</th>
</tr>
</thead>
<tbody>
<tr ng-repeat='item in students' style='height:{{item.w*30}}px'>
<td>{{item.name}}</td>
<td>{{item.number}}</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr>
<th>Books</th>
</tr>
</thead>
<tbody>
<tr ng-repeat='item in books track by $index' style='height:30px'>
<td>{{item}}</td>
</tr>
</tbody>
</table>
</div>
I chose to create hidden nested tables to show more information upon click.

Angularjs Table using JSON data

My two JSON arrays are,
$scope.myHospital = [
{"id":"1","name":"hos1"},
{"id":"2","name":"hos2"},
{"id":"3","name":"hos3"},
{"id":"4","name":"hos4"},
{"id":"5","name":"hos5"}
];
another one is
$scope.data = [
{
"category":"first category",
"procedure":[{
"name":"pro1",
"hospital": [
{"id":"1","price":"1101"},
{"id":"2","price":"1102"},
{"id":"3","price":"1103"},
{"id":"4","price":"1104"},
{"id":"5","price":"1105"}
]
}, {
"name":"pro2",
"hospital": [
{"id":"1","price":"1201"},
{"id":"2","price":"1202"},
{"id":"3","price":"1203"},
{"id":"4","price":"1204"},
{"id":"5","price":"1205"}
]
}, {
"name":"pro3",
"hospital": [
{"id":"1","price":"1301"},
{"id":"3","price":"1303"},
{"id":"5","price":"1305"}
]
}]
},
{
"category":"Second category",
"procedure":[{
"name":"pro4",
"hospital": [
{"id":"1","price":"2101"},
{"id":"2","price":"2102"},
{"id":"3","price":"2103"},
{"id":"4","price":"2104"},
{"id":"5","price":"2105"}
]
}, {
"name":"pro5",
"hospital": [
{"id":"1","price":"2201"},
{"id":"2","price":"2202"},
{"id":"4","price":"2204"}
]
}]
}
];
BY these I want a table like this
I tried it by ng-repeat till now I manage to generate the table here in plnkr
Now I stuck on the logic of null values by matching the hospital id. Inserting null values manually in JSON will not work for me because I am getting this JSON from backend. But I can ask them to change JSON structure(format of array) if needed.
Try smart table. https://github.com/lorenzofox3/Smart-Table
Our prepare your data before ng-repeat to fit your needs.
Not The Exact Solution But May Be Helpful..
<table border="2">
<tbody ng-repeat="cat in data">
<tr>
<td>{{cat.category}}</td>
</tr>
<tr ng-repeat="procedure in cat.procedure">
<td>{{procedure.name}}</td>
<td ng-repeat="hospital in procedure.hospital">{{hospital.price}}</td>
</tr>
</tbody>
Here is the working code.
I have made a bit of changes in your data source too which is easy to consider and make and in HTML too.
In your plunker you were displaying wrong value corresponding to the hospitals when there are few records present in "hospital" object in $scope.data.To rectify that I have added null objects too so the ng-repeat will pass right index for comparision to display
In JS
$scope.data = [
{
"category":"first category",
"procedure":[{
"name":"pro1",
"hospital": [
{"id":"1","price":"1101"},
{"id":"2","price":"1102"},
{"id":"3","price":"1103"},
{"id":"4","price":"1104"},
{"id":"5","price":"1105"}
]
}, {
"name":"pro2",
"hospital": [
{"id":"1","price":"1201"},
{"id":"2","price":"1202"},
{"id":"3","price":"1203"},
{"id":"4","price":"1204"},
{"id":"5","price":"1205"}
]
}, {
"name":"pro3",
"hospital": [
{"id":"1","price":"1301"},
{"id":"2","price":null}, // add null objects for considering right index in display...
{"id":"3","price":"1303"},
{"id":"4","price":null},
{"id":"5","price":"1305"}
]
}]
},
{
"category":"Second category",
"procedure":[{
"name":"pro4",
"hospital": [
{"id":"1","price":"2101"},
{"id":"2","price":"2102"},
{"id":"3","price":"2103"},
{"id":"4","price":"2104"},
{"id":"5","price":"2105"}
]
}, {
"name":"pro5",
"hospital": [
{"id":"1","price":"2201"},
{"id":"2","price":"2202"},
{"id":"3","price":null},
{"id":"4","price":"2204"},
{"id":"5","price":null}
]
}]
}
];
In your HTML
<tr ng-repeat="(index, hos) in myHospital">
<td width="100px">{{hos.name}}</td>
<td width="100px" ng-repeat="pro in d.procedure">
<p ng-show="pro.hospital[index].id == index+1">{{ pro.hospital[index].price }}</p>
<p ng-hide="pro.hospital[index].id == index+1 && pro.hospital[index].price">NULL</p>
</td>
</tr>
You can change the JSON structure after receiving it in order to make it renderable on UI. Something like this,
angular.forEach($scope.data[0].procedure, function(pro) {
var arr = [];
angular.forEach(pro.hospital, function(hos) {
arr[hos.id] = hos.price
});
pro.hospital = arr;
});
Now your hospital array that has lesser values would look like following. If you notice, I changed the structure from array of objects to an array of strings having prices with keys denoting the hospital number..
hospital: [
2: "469",
3: "429",
5: "319"
]
Finally, you can have your rendering logic like following for embracing this change,
<tr ng-repeat="(index, hos) in myHospital">
<td ng-bind="hos.name"></td>
<td ng-repeat="pro in data[0].procedure">
<span ng-bind="pro.hospital[index+1]"></span>
<span ng-if="!pro.hospital[index+1]">NULL</span> <!--Optional-->
</td>
</tr>
DEMO

JS Render For Loop in child JSON object

Trying to make this work. I need to display FIRST_NAME and LAST_NAME values beetween to new TDs. The value are stored in an object of the data item. I can't seem to loop througt the child object.
Template example
<script id="row_tmpl" type="text/x-jsrender">
<tr id="{{>id}}">
<td class="textC">{{>id}}</td>
<td class="">{{>email}}</td>
{{for data}}
??????
{{/for}}
</tr>
</script>
Here is an example of the json object sent to the template ( actually, data.results is sent to the template )
{
"results":[
{
"id":"1",
"email":"aaaa#test.com",
"data":{
"1":{
"first_name":{
"value":"Name 1",
"public":"1",
"field":"1",
"mandatory":"1",
"possible_value":"",
"type":"text"
},
"last_name":{
"value":"Name 2",
"public":"1",
"field":"2",
"mandatory":"1",
"possible_value":"",
"type":"text"
}
}
}
},
{
"id":"2",
"email":"test2#test.com",
"data":{
"2":{
"first_name":{
"value":"Name 3",
"public":"0",
"field":"1",
"mandatory":"1",
"possible_value":"",
"type":"text"
},
"last_name":{
"value":"Name 4",
"public":"0",
"field":"2",
"mandatory":"1",
"possible_value":"",
"type":"text"
}
}
}
}
]
}
That's a poorly structured response. I should not need to know the id of data's parent to access its children. Also, data isn't an array.
<script id="row_tmpl" type="text/x-jsrender">
<tr id="{{>id}}">
<td class="textC">{{>id}}</td>
<td class="">{{>email}}</td>
<td class="">{{>data.{{:id}}.first_name.value}}</td>
<td class="">{{>data.{{:id}}.lastt_name.value}}</td>
</tr>
</script>