AngularJS table using data from REST API - html

I want to display a table using AngularJS. The data source for the table will be a REST API. Here is an example response:
{
"value": 43,
"C_class": [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13
],
"C_name": [
"C_1",
"C_2",
"C_3",
"C_4",
"C_5",
"C_6",
"C_7",
"C_8",
"C_9",
"C_10",
"C_11",
"C_12",
"C_13"
]
}
I want to display the data in the format below:
<tr><td> 1</td><td>C_1<td>
<td>2<td><td>C_2<td>
<td>3<td><td>C_3<td>
<td>4<td><td>C_4<td>
<td>5<td><td>C_5<td>.....
I have tried using ng-repeat, but unable to fetch. Thank you
<table class="table" border="1" style="width: 100%;" id="detail_table">
<tbody><tr ng-repeat="value in tests">
<td>{{value.C_name}}</td>
<td>{{value.C_class}}</td>
</tr></tbody></table>

You are not using ng-repeat in correct way. You can take help from the below code to display your table:
<table class="table" border="1" style="width: 100%;" id="detail_table">
<tbody>
<tr ng-repeat="value in tests.C_class">
<td ng-bind="tests.C_class[$index]"></td>
<td ng-bind="tests.C_name[$index]"></td>
</tr>
</tbody>
</table>
I'll suggest you study a little bit about using ng-repeat.
Try using ng-bind instead of {{}}. see here

This worked for me.
http://plnkr.co/edit/7gLpeyrtyMgnqtdXDxAu?p=preview
<body ng-controller="myCtrl">
<div class="container">
<table class="table table-striped" style="height: 100px; width: 100px;">
<tr ng-repeat="(key,value) in new_c_obj">
<td>{{key}}</td>
<td>{{value}}</td>
</tr>
</table>
</div>
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.response = {
"value": 43,
"C_class": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
"C_name": [ "C_1", "C_2", "C_3", "C_4", "C_5", "C_6", "C_7", "C_8", "C_9", "C_10", "C_11", "C_12", "C_13"]
};
$scope.c_obj = {};
$scope.new_c_obj = {};
$scope.c_obj.c_class = $scope.response["C_class"];
$scope.c_obj.c_name = $scope.response["C_name"];
for($scope.i = 0; $scope.i <= $scope.c_obj.c_class.length-1; $scope.i++){
$scope.new_c_obj[$scope.c_obj.c_class[$scope.i]] = $scope.c_obj.c_name[$scope.i];
}
});

You can use the $index in your ng-repeat (as suggested by B.A.B.U) or properly reformat your data into a new array :
var orgArray = your_data;
var newArray = [];
orgArray.C_class.forEach(function (p, i) {
newArray.push({ C_class: p, C_name: orgArray.C_name[i] });
});
and from there you can apply ng-repeat on the new array to display the fields.

You can simply add those two into another object array..
var mainObjC = array();
C_class.forEach(myFunction);
var x = 0;
function myFunction(){
var obj = {
C_name : C_name[x],
C_class : C_class[x]
}
x++;
mainObjC.push(obj);
}
And your html would be
<table class="table" border="1" style="width: 100%;" id="detail_table">
<tbody>
<tr ng-repeat="value in mainObjC">
<td>{{value.C_name}}</td>
<td>{{value.C_class}}</td>
</tr>
</tbody>
</table>

The format of the data being returned from your API doesn't lend itself well to what you're trying to achieve. You'd have to make assumptions about the the relationship of data between the two arrays. A better structure would be like this:
[
{
"class": 1,
"name": "C_1"
},
{
"class": 2,
"name": "C_2"
},
{
"class": 3,
"name": "C_3"
},
{
"class": 4,
"name": "C_4"
},
{
"class": 5,
"name": "C_5"
}
]
I've created a fiddle which might help, it uses the above data and displays a table with the data: https://jsfiddle.net/9ypkv77x/

Related

JSON map object to the table in React

I have a JSON that is coming like this and I want to show this JSON in the table in React.
{
"Status": true,
"discounts": {
"individual": {
"number_of_cars_discount": {
"1": "1",
"10": "1",
"2": "0.98",
}
}
},
"main_price": {
"client_type": "individual",
"large_car": {
"100": "3",
"1000": "0.9",
"100000": "0.60",
},
}
}
So to do this, I defined
const [mainPrice, setMainPrice] = useState({});
in the parent component and I fetched it like this:
setMainPrice(res.data.main_price);
I sent the mainPrice to the child component where I want to display JSON in the table:
<tbody>
<tr>
<td>
{Object.keys(individualPosts).map((key) => (
<tr>
<td key={key}>{individualPosts[key]}</td>
</tr>
))}
</td>
<td>
{Object.keys(mainPrice.large_car).map((key) => (
<tr>
<td key={key}>{mainPrice.large_car[key]}</td>
</tr>
))}
</td>
</tr>
</tbody>
But it gives me an error: TypeError: Cannot convert undefined or null to object
But I couldnt figure out why.
I have other types of cars like large_cars, small_cars so I need to take the mainPrice like this. I don't want to define all the types of cars and send them to the child component as a props. Or should I make it like this?
Please give me advice and the solution.
Null check required in such cases to avoid errors.
Try this
<td>
{Object.keys(mainPrice?.large_car).length > 0 && Object.keys(mainPrice?.large_car).map((key) => (
<tr>
<td key={key}>{mainPrice.large_car[key]}</td>
</tr>
))}
</td>

Expand only one row in the table

I have a table with rows, where I list the data from json file.
In one row I'm slicing the data to show only 100 symbols.
I want to display full text when user click on the row. I managed to do it, but It opens all rows. How to do it only for the one row, which clicked?
<tr *ngFor="let lfiexport of lfilist | filter:searchText">
<td (click)="fullViewFlag= !fullViewFlag" class="text-left">
<span *ngIf="fullViewFlag">{{lfiexport.desc}}</span>
<span *ngIf="!fullViewFlag">{{lfiexport.desc | slice:0:100}}</span>
</td>
</tr>
You are using same fullViewFlag multiple times, so it will effect all the rows. So, I suggest you maintain different fullViewFlag properties for each object and can try the below code
Working stackblitz
TS file
export class AppComponent {
name = 'Angular ' + VERSION.major;
lfilist = [{
desc: [1, 2, 3, 4, 5, 6]
}, {
desc: [7, 8, 9, 10, 11, 12]
}, {
desc: [13, 14, 15, 16, 17, 18]
}].map(item => {
return {
...item,
fullViewFlag: false
}
});
}
Template file
<tr *ngFor="let lfiexport of lfilist">
<td (click)="lfiexport.fullViewFlag = !lfiexport.fullViewFlag" class="text-left">
<span>{{lfiexport.fullViewFlag ? lfiexport.desc : lfiexport.desc | slice:0:2}}</span>
</td>
</tr>
No need of *ngIf we can use terinary operator ?:

Why is DataTables stripping custom attributes in render function?

I'm working on a .Net MVC website and in one of the views a table is rendered using DataTables which makes an ajax call to an API. However, when the table is rendered the custom attributes I supply in the render function are being stripped out:
Here is the HTML:
<table id="table-rate-headers" class="table table-bordered table-fit table-hover table-sm" style="margin-top: 0px; width: 100%;">
<thead class="text-nowrap">
<tr>
<th>Domain</th>
<th>Project</th>
<th>Union</th>
<th>Union Local</th>
<th>Trade Class</th>
<th>Trade Class Description</th>
<th>Date From</th>
<th>Date To</th>
</tr>
</thead>
<tbody class="text-nowrap"></tbody>
</table>
And the js:
var ratesDataTable = $('#table-rate-headers').DataTable({
dom: 'rftp',
pageLength: 5,
select: true,
ajax: {
url: '/api/rates/rateheadersnormalized',
dataSrc: ""
},
columnDefs: [
{
className: 'row-border'
}
],
columns: [
{
"data": "rateDomain",
render: function (data, type, row) {
return '<td rateheadersid="' + row.rateHeaderSID + '">' + row.rateDomain + '</td>';
}
},
{
"data": "project"
},
{
"data": "union"
},
{
"data": "unionLocal"
},
{
"data": "tradeClass"
},
{
"data": "tradeClassDescription"
},
{
"data": "effectiveDateFrom",
render: function (data, type, row) {
return moment(row.effectiveDateFrom).format("MM/DD/YYYY");
}
},
{
"data": "effectiveDateTo",
render: function (data, type, row) {
return moment(row.effectiveDateTo).format("MM/DD/YYYY");
}
}
]
});
When the page is rendered, I expect to see in the dom:
<td rateheadersid="1">Labor</td>
But what I actually see is:
<td class="sorting_1">Labor</td>
Something is stripping out the custom attribute and not rendering the element as I'd expect. I tried adding "orderClasses": false but it just got rid of the class="sorting_1" and nothing else. Also tried taking out all the css classes I specified for the table and that didn't make a difference. I've also compared the setup of the table to all the previous ones I've created and I can' spot anything out of order. Any guidance appreciated.
The DataTables columns option is already inside the <td> and </td> tags of the HTML table cells it is trying to populate. So, it can only populate the cells content - not the cell's HTML attributes.
HTML does not let you embed another <td> inside a <td> - which is what the code is effectively trying to do.
The simplest fix is to change your <td> to a <span>:
return '<span rateheadersid="' + row.rateHeaderSID + '">' + row.rateDomain + '</span>';
That may be sufficient for your needs. If not, then you may need to provide more info in the question.

Displaying AMCharts inside an HTML table cell

I am trying to display AMCharts inside an HTML table cell. I'm looping through data and creating a chart for each data item. Here is my HTML code:
<table id="theTable" class="display table table-bordered">
<thead>
<tr>
<th>Department</th>
<th>Number of Employees</th>
<th>Number of Volunteers</th>
<th>Chart</th>
</tr>
</thead>
<tbody>
<tr>
<td>IT</td>
<td>30</td>
<td>5</td>
<td><div id="chart_1"></div></td>
</tr>
<tr>
<td>HR</td>
<td>35</td>
<td>14</td>
<td><div id="chart_2"></div></td>
</tr>
<tr>
<td>LG</td>
<td>100</td>
<td>65</td>
<td><div id="chart_3"></div></td>
</tr>
</tbody>
</table>
And here is my Javascript code:
var emp = [30, 35, 100];
var vol = [5, 14, 65];
for (var j = 0; j < 3; j++) {
var str = "chart_" + j.toString();
var chart = AmCharts.makeChart(str, {
"type": "pie",
"dataProvider": [{
"type": "Employees",
"per": parseFloat(emp[j]),
"color": "#54e83a"
}, {
"type": "Volunteers",
"per": parseFloat(vol[j]),
"color": "#41ba2c"
}],
"valueField": "per",
"titleField": "type",
"colorField": "color",
"balloon": {
"fixedPosition": true
},
"export": {
"enabled": true
},
"startDuration": 0
});
}
What am I doing wrong? Any help is appreciated! Here is a JSFiddle
(Please ignore this text the Editor is saying my post is mostly code so I'm adding non-code text hoping to trick it...This is unprofessional I know.)
AmChart divs must have dimensions specified through CSS, otherwise they won't display. Set the sizes and you're all set, for example:
#chart_1, #chart_2, #chart_3 {
width: 300px;
height: 100px;
}
You also need to adjust your loop logic as you're starting from chart_0, when your divs are starting from chart_1. Either update your html or fix your string creation, e.g. var str = "chart_" + (j + 1); (note you don't need toString())
Updated fiddle

Iterating through JSON data with Mustache JS

I have been trying and failing to iterate through some JSON Data with Mustache JS in order to populate a table which looks like:
{
"Pay":[
[
"Regular Hours",
"$75.00",
"$75.00"
]
],
"Earnings":[
[
"Regular Earnings",
"$2,277.00",
"$1,200.00"
],
[
"Non Tax Vacation Pay",
"$0.00",
"$50.80"
]
],
"Deductions":[
[
"Other Deduction 5",
"$0.00",
"$50.00"
]
]
}
How would I iterate using Mustache JS in order to have every inner array as rows and the outer array as headers like this:
<tr>
<th colspan="4">Pay</th>
</tr>
<tr>
<td>Regular Hours</td>
<td>75</td>
<td>75</td>
</tr>
<!-- Etc. -->
Any help would be greatly appreciated
This issue has made me consider switching over to handlebars to avoid the need for hacky code. The data being passed in is the JSON input from the original question. This function will format the data into key value pairs, after which the data is rendered by the Mustache template.
function (data) {
var payslipList = JSON.parse(data.d);
formattedData = { 'entries': [] };
for (var property in payslipList) {
if (payslipList.hasOwnProperty(property)) {
formattedData['entries'].push({
'key': property,
'value': payslipList[property]
});
}
}
var tablePayslip = $("#tblPayDetails tbody");
$.each(formattedData, function (id, payslip) {
var template = $('#renderPaystub').html();
var html = Mustache.render(template, payslip);
tablePayslip.append(html);
});
The template to access the key value pairs would look something like this:
<script type="text/template" id="renderPaystub">
{{#.}}
{{#.}}
<tr>
<th colspan="3">{{key}}</th>
</tr>
{{/.}}
{{#value}}
<tr>
{{#.}}<td>{{.}}</td>{{/.}}
</tr>
{{/value}}
{{/.}}
</script>
This template is fairly ugly and ambiguous, if there is a better method to achieve this, feel free to let me know.