JSON map object to the table in React - json

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>

Related

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!

Cannot print a table with *ngFor from a 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>

Is it possible to get the length of a firebase JSON object when using vuefire?

I have the following firebase JSON object:
"items" : {
"111111111111" : {
"ins" : { <<<<<<<<< I want to display the length of this
"1523878813443" : true,
"1523878891312" : true,
"1523878911379" : true,
"1523879091312" : true
},
"name" : "10",
"outs" : { <<<<<<<<< and this one too
"1523878813443" : true,
"1523878891312" : true,
"1523878911379" : true
},
"ownerID" : "QpMHsVHHRrMvk92rbSQvcYEv4en1"
}
}
Here is the template part on where I am trying to get these values to update:
<tbody>
<tr v-for="item in items" >
<td>
{{item.childone - door.childtwo}}
</td>
<td>
{{item.childone}}
</td>
<td>
{{item.childtwo}}
</td>
</tr>
</tbody>
I got it to display the JSON object like this:
The "In's" column should display 4, the "Out's" should display 3 and the "Balance" column should display 1.
This is the firebase setup and data code on my component:
import firebase { doorsRef } from '../firebase-config';
export default {
firebase() {
return {
items: itemsRef,
}
},
...etc
}
Any kind soul out there who would be willing to help?
Knowing that a JSON object has keys (and values) I have used this on my template instead:
{{Object.keys(JSON.Object).length}}
So in my case this did the trick:
<tbody>
<tr v-for="item in items" >
<td>
{{Object.keys(item.childone).length - Object.keys(item.childtwo).length}}
</td>
<td>
{{Object.keys(item.childone).length}}
</td>
<td>
{{Object.keys(item.childtwo).length}}
</td>
</tr>
</tbody>
Alternative you you can also count the number of values: {{Object.values(JSON.Object).length}}

Test Velocity Template

I do have a velocity template something like
<TABLE>
<TH>
NAME
</TH>
<TR>
$!{name}
</TR>
.....other code......
#foreach( $!{grade} in $!{student.gradeList} )
<tr>
<td align="center">$!{grade.mathGrade}</td>
<td align="center">$!{grade.scienceGrade}</td>
</tr>
#end
below is my json file
{
"name":"xyz",
...other variables....
}
So, now I want to test this, but I am getting error that Variable $student has not been set. I checked that $student is not defined anywhere else in template. I tried to give random string value for that something like "student":"XYZ" but then it gave error that String does not have property named gradeList. How to solve this?
I found the solution, where I added student as an object in my json file something like:
{
"name": "XYZ",
"student": {
"gradeList": [
{
"mathGrade": "A"
},
{
"scienceGrade": "B"
}
]
}
}

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;
}
}