Cannot print a table with *ngFor from a json - json

This particular Json does not have the key of each element in the arrays, I managed to make this work with other Jsons which bring the element keys and use those keys in the {{data.key}} to print with *ngFor.
I tried more than 25 solutions in stackoverflow but it seems that my case is unique, no one else uses a JSON without keys/labels to create a table.
This is my Json:
{
"data": {
"spnf": {
"anios": [
"2018-Q4",
"2018-Q4"
],
"titulos": [
"Ingresos Totales",
"Balance Total"
],
"anioactual": [
3183,
-837
],
"anioanterior": [
3672,
1549
]
},
"gob_central": {
"anios": [
"2018-Q4",
"2018-Q4"
],
"titulos": [
"Ingresos Totales",
"Balance Total"
],
"anioactual": [
3183,
-837
],
"anioanterior": [
3672,
1549
]
}
}
}
This is my balances.ts:
{
this.loader.present().then(() => {
this.finanzaService.getBalances2()
.subscribe((result) => {
this.dataRequest = result;
this.setData();
// Disable Loader
this.loader.dismiss();
}, (err) => {
"error blah blah"
}
);
});
}
public setData(tipo: string = 'spnf') {
if (tipo == 'spnf') {
this.dataResumen = _.clone(this.dataRequest.spnf);
} else {
this.dataResumen = _.clone(this.dataRequest.gob_central);
}
}
This is my finanzapublica.service.ts:
public getBalances2(): Observable<any>{
const url = `${this.apiURL}/balances_fiscales/balances_datos2.json`;
return this.http.get(url, this.options)
.map((res: Response) => res.json().data);
}
This is my balances.html, as soon as I try this.dataResumen, the app breaks and throws error: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.
<table *ngIf="dataRequest">
<thead>
<tr>
<td class="border" text-center>Rubro</td>
<td class="border" *ngFor="let data of this.dataResumen.anios" text-center>{{ data }}</td> <!--this works-->
</tr>
</thead>
<tbody>
<tr *ngFor="let data of this.dataResumen"><!--this doesn't work-->
<td class="border" text-center>{{data.titulos}}</td>
<td class="border" text-center>{{data.anioactual}}</td>
<td class="border" text-center>{{data.anioanterior}}</td>
</tr>
</tbody>
</table>
This is the error:
Cannot find a differ supporting object '{
"anios": [
"2018-Q4",
"2018-Q4"
],
"titulos": [
"Ingresos Totales",
"Balance Total"
],
"anioactual": [
3183,
-837
],
"anioanterior": [
3672,
1549
]
}' of type 'string'. NgFor only supports binding to Iterables such as Arrays.
The result I wanted is like:
Rubros 2018-Q4 2018-Q4
Ingresos Totales 3183 3672
Balance Total -837 1549

<table>
<thead>
<tr>
<td class="border" text-center>Rubro</td>
<td class="border" *ngFor="let data of dataResumen?.anios" text-center>{{ data }}</td> <!--this works-->
</tr>
</thead>
<tbody>
<tr *ngFor="let data of dataResumen.titulos; let i=index;">
{{data}}
<td>{{dataResumen.anioactual[i]}}</td>
<td>{{dataResumen.anioanterior[i]}}</td>
</tr>
</tbody>
</table>

Related

Unable to Fetch JSON Response in VueJS

My goal: I'm trying to create a table in VueJS and populate it with data from a JSON file.
JSON file:
{
"users": [
{
"id_num": 1,
"name": "Max",
"date_registered": "2021-05-15"
},
{
"id_num": 2,
"name": "Sabrina",
"date_registered": "2021-07-23"
},
{
"id_num": 3,
"name": "Sasha",
"date_registered": "2021-09-02"
}
]
}
My table (located in the template section of its respective component file in VueJS):
<body>
<div class="container mt-4" id="app">
<table class="table table-bordered">
<thead>
<tr>
<th scope="col">
ID Number
</th>
<th scope="col">
Name
</th>
<th scope="col">
Date of Registration
</th>
</tr>
</thead>
<tbody>
<tr v-for="user in users" :key="user.id" class="user">
<td>{{ user.id_num }}</td>
<td>{{ user.name }}</td>
<td>{{ user.date_registered}}</td>
</tr>
</tbody>
</table>
</div>
</body>
My fetch call (located in the script section of the same component file as my table):
export default {
data() {
return {
users: [],
};
},
mounted() {
fetch('http://localhost:3000/users')
.then((response) => response.json())
// eslint-disable-next-line no-return-assign
.then((data) => (this.users= data))
.catch((err) => console.log(err.message));
},
};
My result when I test locally: I see the first row with the three columns of my table (ID Number, Name, Date of Registration) but that's all. There are no rows with the info from my API. When I open the console, it says Failed to load resource: net::ERR_CONNECTION_REFUSED :3000/users:1 and Failed to fetch.

Angular: Dynamically find headers when converting JSON array to HTML table

In Angular, I want to convert a JSON array to an HTML table.
I have seen an old answer for AngularJS:
<table>
<thead>
<tr>
<th ng-repeat="(key, value) in records[0]">{{key}}</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="(key, value) in records">
<td ng-repeat="(key, value) in value">
{{value}}
</td>
</tr>
</tbody>
</table>
JSON looks like this:
[{
"Name": "Alfreds Futterkiste",
"City": "Berlin",
"Country": "Germany"
}, {
"Name": "Berglunds snabbköp",
"City": "Luleå",
"Country": "Sweden"
}, {
"Name": "Centro comercial Moctezuma",
"City": "México D.F.",
"Country": "Mexico"
}]
I've tried to translate it to the Angular syntax. Here is what I got so far:
<table>
<thead>
<tr>
<th *ngFor="let item of records[0] | keyvalue">{{item.key}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of records">
<td *ngFor="let item1 of item | keyvalue">
{{item1.value}}
</td>
</tr>
</tbody>
</table>
Right now it's failing to compile because records[0] is undefined... how can I translate this expression to the newer syntax (or create something equivalent)?
UPDATE 1:
I have a partial solution. However with this partial solution the rendered table is not completely identical to the older AngularJS rendition (because it creates multiple unnecessary header rows, which only one of them is populated, as opposed to only one header row in the older rendition).
<table style="border-collapse: collapse;">
<thead *ngFor="let item of records; let last=last">
<tr *ngIf="last">
<th *ngFor="let item1 of item | keyvalue">
{{item1.key}}
</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of records">
<td *ngFor="let item1 of item | keyvalue">
{{item1.value}}
</td>
</tr>
</tbody>
</table>
Do you have a better way to do it, possibly similar to the older AngularJS version?
UPDATE 2:
In Angular, I access the JSON data through a request from Angular that is then redirected to a back end service. That service may read a file, or get the data from a database. When the back end service has the data ready, it returns the data to the Angular request. The code on the Angular end looks like this:
HTML:
<div>
<h3>Test Post Request</h3>
<button (click)="postData()">Click Me</button>
<div>Response: {{records}}</div>
</div>
TypeScript:
private dataPostTestUrl = '/api/postTest';
records: string | undefined;
public postData(): void {
this.appService.sendData().subscribe((data: any) => {
this.records = data.content;
});
}
public sendData(): Observable<any> {
return this.http.post(this.dataPostTestUrl, {});
}
I think maybe you need to define records in the component.
records = [{
"Name": "Alfreds Futterkiste",
"City": "Berlin",
"Country": "Germany"
}, {
"Name": "Berglunds snabbköp",
"City": "Luleå",
"Country": "Sweden"
}, {
"Name": "Centro comercial Moctezuma",
"City": "México D.F.",
"Country": "Mexico"
}];
I am fairly certain this is what you need: https://stackblitz.com/edit/angular-ivy-n7irpw?file=src/app/hello.component.ts
Take a look at how I import the file in the app.component.ts
As well as how I loop in the HTML.
Let me know if it helps!

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>

Nested ng-repeat in AngularJS

I have the following JSON:
{ "ListNhomThanhTra": [
{
"ListKeHoachThanhTra": [
{
"ListDoiTuong": [
{
"MA_DV_DUOC_TT": "DT01",
"TEN_DOITUONG": "Tỉnh Bắc Ninh",
"stt": 1.1
}
],
"MA_DM_KEHOACH_TT": "KH13072018003",
"TEN_KEHOACH": "Kế hoạch chính thức",
"stt": 1
}
],
"MA_NHOM_TT": "010",
"TEN_NHOM": "Thanh tra ngân sách địa phương",
"stt": "I"
},
{
"ListKeHoachThanhTra": [
{
"ListDoiTuong": [
{
"MA_DV_DUOC_TT": "DT01",
"TEN_DOITUONG": "Tỉnh Bắc Ninh",
"stt": 1.1
}
],
"MA_DM_KEHOACH_TT": "KH13072018003",
"TEN_KEHOACH": "Kế hoạch chính thức",
"stt": 1
}
],
"MA_NHOM_TT": "02",
"TEN_NHOM": "Thanh tra tài chính, bộ ngành",
"stt": "II"
}
],
"MA_LOAI_TT": "01",
"TEN_LOAI": "Kế hoạch thanh tra",
"stt": "A"
}
Currently, I have a JSON string like this, and I want to display it in a tabular form.
I tried to use the code below, but it just stops at the second ng-repeat, and it's not going any further, so I was wondering how do I do it right?
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<tbody ng-repeat="loaiThanhTra in dataTable">
<td>{{loaiThanhTra.stt}}</td>
<td>{{loaiThanhTra.TEN_LOAI}}</td>
<tr ng-repeat="nhomThanhTra in loaiThanhTra.ListNhomThanhTra">
<td>{{nhomThanhTra.stt}}</td>
<td>{{nhomThanhTra.TEN_NHOM}}</td>
<tr ng-repeat="keHoachThanhTra in nhomThanhTra.ListKeHoachThanhTra ">
<td>{{keHoachThanhTra.stt}}</td>
<td>{{keHoachThanhTra.TEN_KEHOACH}}</td>
<tr ng-repeat="doiTuongThanhTra in keHoachThanhTra.ListDoiTuong">
<td>{{doiTuongThanhTra.stt}}</td>
<td>{{doiTuongThanhTra.TEN_DOITUONG}}</td>
</tr>
</tr>
</tr>
</tbody>
Please help me!!!
You cannot have trs in tds. Use ng-container and row spans on your parent objects.
<tbody ng-repeat="loaiThanhTra in dataTable">
<td>{{loaiThanhTra.stt}}</td>
<td>{{loaiThanhTra.TEN_LOAI}}</td>
<tr ng-repeat="nhomThanhTra in loaiThanhTra.ListNhomThanhTra">
<td rowspan="nhomThanhTra.ListKeHoachThanhTra.length">{{nhomThanhTra.stt}}</td>
<td rowspan="nhomThanhTra.ListKeHoachThanhTra.length">{{nhomThanhTra.TEN_NHOM}}
</td>
<ng-container ng-repeat="keHoachThanhTra in nhomThanhTra.ListKeHoachThanhTra ">
<td rowspan="keHoachThanhTra.ListDoiTuong.length">{{keHoachThanhTra.stt}}</td>
<td rowspan="keHoachThanhTra.ListDoiTuong.length">{{keHoachThanhTra.TEN_KEHOACH}}</td>
<ng-container ng-repeat="doiTuongThanhTra in keHoachThanhTra.ListDoiTuong">
<td>{{doiTuongThanhTra.stt}}</td>
<td>{{doiTuongThanhTra.TEN_DOITUONG}}</td>
</ng-container>
</ng-container>
</tbody>

Unable to iterate *ngFor loop with array of column in table

I have table like this which i want to iterate
Heating Diesel Benzin Fracht
43.10 87.15 108.00
43.35 87.40 108.25
43.80 87.80 108.60 2394.00
----- ----- ----- ----
Here is json data which i want to insert into my table and here first object is one column, second object is second column like that i need to insert 4 columns. i don't understand how to iterate this with *ngFor loop. please excuse if any thing wrong in my question.
[
{
"s4": "43,10",
"s5": "43,35",
"s6": "43,80",
"s7": "43,90",
"s8": "44,10",
"s15": "64,25",
"s9": "44,55",
"s10": "43,20",
"s11": "43,90",
"s16": "54,00"
},
{
"s4": "87,15",
"s5": "87,40",
"s6": "87,80",
"s7": "87,90",
"s8": "88,05",
"s15": "121,05",
"s9": "88,60",
"s10": "87,30",
"s11": "88,00",
"s16": "80,90"
},
{
"s4": "108,00",
"s5": "108,25",
"s6": "108,60",
"s7": "108,70",
"s8": "108,85",
"s15": "119,65",
"s9": "109,30",
"s10": "108,50",
"s11": "109,00",
"s16": "92,25"
},
{
"s4": "",
"s5": "",
"s6": "2394,02",
"s7": "12,29",
"s8": "2395,46",
"s15": "",
"s9": "2386,92",
"s10": "22:05",
"s11": "",
"s16": ""
}
]
<table *ngIf="indexdata">
<tr style="color: #3B6593" >
<th><strong>Heizöl</strong></th>
<th><strong>Diesel</strong></th>
<th><strong>Benzin</strong></th>
<th><strong>Facht</strong></th>
</tr>
<tr *ngFor="let index of indexdata;let i=index">
<td>{{index.s4}}</td>
<td>{{index.s5}}</td>
<td>{{index.s6}}</td>
-----
-----
</tr>
</table>
Your code should be
<table *ngIf="indexdata">
<tr style="color: #3B6593">
<th><strong>Heizöl</strong></th>
<th><strong>Diesel</strong></th>
<th><strong>Benzin</strong></th>
<th><strong>Facht</strong></th>
</tr>
<tr>
<td *ngFor="let indexvalue of indexdata">
<table>
<tr *ngFor="let indexobj of indexvalue | keys">
<td>
{{indexobj.value}}
</td>
</tr>
</table>
</td>
</tr>
</table>
You could create a custom pipe to return the list of key for each element. Something like this:
#Pipe({name: 'keys'})
export class KeysPipe implements PipeTransform {
transform(value, args:string[]) : any {
let keys = [];
for (let key in value) {
keys.push({key: key, value: value[key]});
}
return keys;
}
}