Looping over JSON array using *ngFor - json

I currently have the following JSON file:
[
{
"Arsenal": {
"form": {
"away": 4.6064800860172,
"home": 2.2108841763771
},
"stadium": "Stadium 1"
}
},
{
"Man City": {
"form": {
"away": 4.9473459270023,
"home": 5
},
"stadium": "Stadium 2"
}
},
{
"Man Utd": {
"form": {
"away": 5,
"home": 3.2296790061981
},
"stadium": "Stadium 3"
}
}
]
and I want to display this data in a table. I currently have a service that retrieves the JSON file and returns it
public getJSON(): Observable<any> {
return this.http.get('assets/teams.json')
.map(
(response: Response) => {
const data = response.json();
return data;
}
);
}
I then subscribe to it in my component and save it to teams.
teams = [];
loadJSON() {
this.teamService.getJSON().subscribe(
(teams: any[]) => this.teams = teams,
(error) => console.log(error)
);
}
and using the following HTML
<div class="container">
<table class="table">
<thead>
<tr>
<th>Team</th>
<th>Home</th>
<th>Away</th>
<th>Stadium</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let team of teams | keys">
<td>{{ (team.value | keys)[0].key }}</td>
<td>{{ (team.value | keys)[0].value["form"]["home"] }}</td>
<td>{{ (team.value | keys)[0].value["form"]["away"] }}</td>
<td>{{ (team.value | keys)[0].value["stadium"] }}</td>
</tr>
</tbody>
</table>
</div>
gives the table seen below
Surely there must be a better way of doing this? How can I do this in a more straight-forward way, that is a lot more readable? For example, if the key was actually "Arsenal", "Man City" and "Man Utd" instead of 0, 1 and 2 respectively, it would be much more readable. Why does it have those keys instead? I'm used to coding in Python so it doesn't really make much sense to me.
A working stackblitz can be found here.

I propose to have your own Team object and map your JSON on it.
So in your teams.service you have:
public getJSON(): Observable<Team[]> {
return this.http.get('assets/teams.json')
.map(teams => teams.map(team => this.mapTeam(team)))
}
private mapTeam(res: any): Team {
const teamName = Object.keys(res)[0]
return new Team(
teamName,
{away: res[teamName].form.away, home: res[teamName].form.home},
res[teamName].stadium
)
}
Your Team class can be like this:
export class Team {
constructor(public name: string,
public form: { away: number, home: number },
public stadium: string) {
}
}
It's not the subject of your question but in this the Team class it's preferable to have private properties and have getter to access it.
In your component.ts:
Just call your service and assign the value of the subscribe: this.teamService.getJSON().subscribe(value => this.teams = value)
There are antother way to do this part but it's not your question too
And finally your html it's more readable:
<div class="container">
<table class="table">
<thead>
<tr>
<th>Team</th>
<th>Home</th>
<th>Away</th>
<th>Stadium</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let team of teams">
<td>{{ team.name }} </td>
<td>{{ team.form.home }}</td>
<td>{{ team.form.away }}</td>
<td>{{ team.stadium }}</td>
</tr>
</tbody>
</table>
</div>
The stackblitz here: https://stackblitz.com/edit/angular-gwj6nb

Related

Why I cannot see json data in table?

I am trying to display json data in tree hierachy table with vue.js. Unfortunally I cannot see any data inside of the table. The path is correct, I have checked this by URL adress, the format as well. My goal is to create tree hierarchy table, with action button for removing layers. I would like to mention thath I am new in Vue.js framework, so this is not maybe the best option how to work with fetched data from json file.
HTML:
<table>
<thead>
<tr>
<th>Name</th>
<th>Parent</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr v-for="item in items" :key="item.id">
<td>{{ item.name }}</td>
<td>{{ item.parent }}</td>
<td>
<button #click="toggleChildren(item)">Toggle Children</button>
</td>
<template v-if="item.childrenVisible">
<tr v-for="child in item.children" :key="child.id">
<td>{{ child.name }}</td>
<td>{{ child.parent }}</td>
<td>
<button #click="toggleChildren(child)">Toggle Children</button>
</td>
</tr>
</template>
</tr>
</tbody>
</table>
</div>
Vue.js code
<script>
fetch('data/vue-data.json')
.then(response => response.json())
.then(data => {
new Vue({
el: '#app',
data: {
items: data.items
},
methods: {
toggleChildren(item) {
item.childrenVisible = !item.childrenVisible;
},
}
});
})
</script>
you create your app in advance. also where is your #app container?
<div id="app">
<!-- your table data -->
</div>
and for the js
new Vue({
el: '#app',
// data should return an object, not be an object
data() {
return {
items: [] // default value, could also be null
}
},
// called on initialization, read about lifecycle hooks
mounted() {
fetch('data/vue-data.json').then(response => { this.items = response.json() })
},
methods: {
toggleChildren(item) {
item.childrenVisible = !item.childrenVisible;
},
}
});

Put json data into table

I actually want to create a table with the data who the api return to me.
The problem is that i can't print the data.
The IdLangage have his column in the table and i want to put the data of the traduction into the correct cell.
The JSON data format :
traductionData ={
"Data":
[
{
"Code": "BJR",
"TraductionsFormat":
[{
"Code": "BJR",
"Description": null,
"Id": 0,
"IdLangage": "FR",
"Traduction": "Bonjour"
},
{
"Code": "BJR",
"Description": null,
"Id": 0,
"IdLangage": "EN",
"Traduction": "Hello"
}]
},
] };
Here is my table where i want to print the data into :
<table>
<thead>
<tr>
<th width="25%">Code</th>
<th width="15%">FR</th>
<th width="15%">EN</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let traduction of traductionData">
<td>{{ traduction.TraductionsFormat.Code }}</td>
<td>{{ traduction.TraductionsFormat.Traduction}}</td>
</tr>
</tbody>
</table>
Here is my angular service :
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http'
import { map } from 'rxjs/operators';
import { environment } from 'src/environments/environment';
#Injectable({
providedIn: 'root'
})
export class ApiService {
localUrlAPI: string = environment.urlAPI;
constructor(private http : HttpClient) { }
getAllTraductions(){
return this.http.get<any>(this.localUrlAPI+"GetAllTraductionsGroupByCode")
.pipe(map((res:any)=>{
return res;
console.log(res);
}))
}
}
And here is my angular Component with my http request :
import { Component, OnInit } from '#angular/core';
import { ApiService } from 'src/app/services/api.service';
#Component({
selector: 'app-grid-edit-traductions',
templateUrl: './grid-edit-traductions.component.html',
styleUrls: ['./grid-edit-traductions.component.scss']
})
export class GridEditTraductionsComponent implements OnInit {
traductionData !: any[];
constructor(private api: ApiService) { }
ngOnInit(): void {
this.getLesTraductions();
}
getLesTraductions(){
this.api.getAllTraductions()
.subscribe(res=>{
this.traductionData = res.Data;
console.log(this.traductionData)
})
}
}
<table>
<thead>
<tr>
<th *ngFor="let column of tableHeaders">
{{column}}
</th>
</tr>
</thead>
<tbody>
<tr ng *ngFor="let row of tableRows">
<td *ngFor="let column of tableHeaders">
{{row[column]}}
<ng-container *ngFor="let trad of row.TraductionsFormat, let j = index">
<span *ngIf="row.TraductionsFormat[j].IdLangage === column">
{{row.TraductionsFormat[j].Traduction}}
</span>
</ng-container>
</td>
</tr>
</tbody>
</table>
Here's the ts:
tableRows: Array<any> = [];
tableHeaders: Array<any> = [];
ngOnInit(): void {
//---- TABLE HEADERS -----
this.tableHeaders.push("Code")
this.traductionData.Data.forEach(el => {
el.TraductionsFormat.map(c => c.IdLangage).forEach(lang => {
this.tableHeaders.push(lang);
})
});
this.tableHeaders = [...new Set(this.tableHeaders)];
//---- TABLE ROWS -----
this.traductionData.Data.forEach(el => {
this.tableRows.push(el)
});
}
Stackblitz example
The JSON data you've provided is wrong, there are missing commas and brackets. Although, I'm pretty sure that the reason the data isn't shown in table is that the "TraductionsFormat" is an array. If you want to get an item from array you have to provide an index.
<tr *ngFor="let traduction of traductionData">
<td>{{ traduction.TraductionsFormat[0].Code }}</td>
<td>{{ traduction.TraductionsFormat[0].Traduction}}</td>
</tr>
Above is just simple solution. You might want to use dynamic indexes.

how do i loop through a json object from an api in vuejs?

/Dear All,
I would like to create a table from this API created JSON object, how can I use v-for in Vue js ? design is not important I just cannot implement v-for in this case? the table should not be fancy just a plane html table/
<template>
<div id="app">
<table>
<thead>
<tr>
<th>id</th>
<th>meta</th>
<th>title</th>
<th>is private</th>
</tr>
</thead>
</table>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
return {
items:''
}
},
created() {
axios.get(`https://zbeta2.mykuwaitnet.net/backend/en/api/v2/pages/`)
.then(response => {
this.items = response.data
})
}
}
</script>
<style>
</style>
Your HTML table:
<table>
<thead>
<tr>
<th>id</th>
<th>meta</th>
<th>title</th>
<th>is private</th>
</tr>
</thead>
<tbody>
<tr v-for="item in items" :key="item.id">
<td>{{ item.id }}</td>
<td>{{ item.meta.detail_url }}</td>
<td>{{ item.title }}</td>
<td>{{ item.is_private }}</td>
</tr>
</tbody>
</table>
Script:
async created() {
const response = await axios.get(
`https://zbeta2.mykuwaitnet.net/backend/en/api/v2/pages/`
);
this.items = response.data.items;
},

Deserialize of an API response and display it in view loop

I have a problem with response deserialization. What is the best way to deserialize data to projects and display it in view in the simplest way? My IDE doesn't find map() method.
Response:
{
"totalCount": 2,
"items": [
{
"title": "TestProject1",
"id": 1
},
{
"title": "TestProject2",
"id": 2
}
]
}
Typescript:
private usertoken: string;
private projects: any;
constructor(private http: HttpClient, private cookie : CookieService) { }
ngOnInit() {
this.usertoken = this.cookie.get('usertoken');
console.log("asdasdasd1");
this.http.get("https://localhost:5001/api/abc/cba",
{headers: new HttpHeaders().set('Authorization', 'Bearer ' + this.usertoken)})
.subscribe(data =>{
this.projects = data;
});
Html:
<table>
<tr *ngFor="let project of projects">
<th scope="row">{{ project.totalCount }}</th>
<!-- <td>{{ project.projectName }}</td> -->
</tr>
</table>
As #Nico suggested, you are iterating the wrong object. If you set the data directly in the projects, you have the projects.Items and project.TotalCount, so you should make the for in the Items which is the array.
<tr *ngFor="let project of projects.items">
<th scope="row">{{ projects.totalCount }}</th> //Get total Count from the main object
<td>{{ project.title }}</td> //Get name from the items interaction
</tr>

How to fetch data from console output to table using angular2

I have a table in HTML, i need to fetch data from consoled output to the table. Please help.
HTML Code:
<table class="table">
<tr>
<th>Completed On</th>
<th>ID</th>
<th>ParticipantId</th>
</tr>
<tr *ngFor="let data of result">
<td>{{ data.completedOn }}</td>
<td>{{ data.id }}</td>
<td>{{ data.participantId }}</td>
</tr>
</table>
TS Code:
public result:any = [];
this.service
.getParticipent(comparedCampaign.id,token)
.subscribe(
participent => {
this.loading = false;
// this.result = data;
console.log( this.result);
var survey = this.surveyResults;
if(participent.length > 0) {
var data =[];
participent.map(function(item) {
var list = survey.filter(function(result) {
if(result.participantId) {
return result.participantId == item.id
}
})
data.push(list);
this.result = data;
console.log( this.result);
})
console.log(data);
} else {
alert('No Participent found!');
}
}, error => {
console.log(error)
})
}
}
From this i need to fetch CompletedOn, id and participantId to the table
JSON Consoled output:
[[{"satisfaction":"[object Object]","completedOn":"2017-08-22T08:52:55.788Z","id":3,"participantId":217},{"satisfaction":{"price":"less","recomondation":"1","winback":"reason6"},"completedOn":"2017-08-22T09:12:40.800Z","id":4,"participantId":217},{"satisfaction":{"price":"less","recomondation":"1","winback":"reason6"},"completedOn":"2017-08-22T11:36:04.861Z","id":5,"participantId":217},{"satisfaction":{"price":"less","recomondation":"1","winback":"reason6"},"completedOn":"2017-08-22T11:59:24.334Z","id":6,"participantId":217},{"satisfaction":{"price":"medium","customer":"yes","recomondation":"2","sales":["phone","Shop","webshop"],"webVist":"5","shopVist":"5","phoneVist":"5","prodandService":["{product_list}"],"importance":["Service"],"frequence":"quarter","satisfaction":"3"},"completedOn":"2017-08-22T12:20:54.280Z","id":7,"participantId":217},{"satisfaction":{"price":"medium","customer":"no","recomondation":"1","winback":"reason1","winback_quality":"reason2"},"completedOn":"2017-08-22T12:22:43.153Z","id":8,"participantId":217},{"satisfaction":{"prodandService":[{"index":"Orbiz"},{"index":"qwerq"},{"index":"asfd"},{"index":"test"},{"index":"test123"},{"index":"TestWD"},{"index":"IOS app"},{"index":"Lipstick"},{"index":"Foundation"},{"index":"lipstick"},{"index":"Website"},{"index":"App IOS"},{"index":"Shampoo Vanilla"},{"index":"Shampoo Strawberry"},{"index":"car"},"Lipstick"],"price":"medium","customer":"yes","recomondation":"4","sales":["phone"],"phoneVist":"3","importance":["Quality"],"frequence":"quarter","satisfaction":"3"},"completedOn":"2017-08-28T09:39:54.676Z","id":10,"participantId":217},{"satisfaction":{"prodandService":[{"index":"Orbiz"},{"index":"qwerq"},{"index":"asfd"},{"index":"test"},{"index":"test123"},{"index":"TestWD"},{"index":"IOS app"},{"index":"Lipstick"},{"index":"Foundation"},{"index":"lipstick"},{"index":"Website"},{"index":"App IOS"},{"index":"Shampoo Vanilla"},{"index":"Shampoo Strawberry"},{"index":"car"},"Foundation","IOS app","test123","test"],"price":"medium","customer":"yes","recomondation":"5","sales":["visits"],"salesVist":"3","importance":["Quality"],"frequence":"year","satisfaction":"5","knowledge":["IOS app","Foundation","Website"],"development":"littleLess","suppliers":"yes","competators":"60","competators_reasons":"Quality","Need":["{product_list}"],"service":"5","collaboration":"4","continuedCollaboration":"3","improvements":["Service","Price"],"winback":"reason3"},"completedOn":"2017-08-28T14:45:13.991Z","id":11,"participantId":217},{"satisfaction":{"prodandService":[{"index":"Orbiz"},{"index":"qwerq"},{"index":"asfd"},{"index":"test"},{"index":"test123"},{"index":"TestWD"},{"index":"IOS app"},{"index":"Lipstick"},{"index":"Foundation"},{"index":"lipstick"},{"index":"Website"},{"index":"App IOS"},{"index":"Shampoo Vanilla"},{"index":"Shampoo Strawberry"},{"index":"car"},"TestWD","Lipstick"],"price":"less","recomondation":"4","sales":["phone"],"phoneVist":"3","importance":["Quality","Assortment"],"frequence":"quarter","satisfaction":"4","knowledge":["IOS app"],"Need":["TestWD","Lipstick"],"development":"same","suppliers":"yes","competators":"60","competators_reasons":"Assortment","service":"4","collaboration":"4","continuedCollaboration":"3","improvements":["Assortment"],"winback":"reason4"},"completedOn":"2017-09-01T14:23:04.533Z","id":13,"participantId":217}]]
with error:
"EXCEPTION: Cannot set property 'result' of undefined"
Please Help.
Thanks in advance
You need to access the 0th index of the array and then assign to the result,
this.service.getParticipent(comparedCampaign.id,token).subscribe(
participent => {
this.result = participent[0];
}
then you can iterate over and display as you mentioned above,
<tr *ngFor="let data of result">
<td>{{ data.completedOn }}</td>
<td>{{ data.id }}</td>
<td>{{ data.participantId }}</td>
</tr>
i guess you are showing array in wrong format so try this
this.service.getParticipent(comparedCampaign.id,token).subscribe(
participent => {
this.result = participent;
}
and use your array like this
<tr *ngFor="let data of result">
<td>{{ data?.completedOn }}</td>
<td>{{ data?.id }}</td>
<td>{{ data?.participantId }}</td>
</tr>
also please try to print whole array in HTML too, for better understanding like this
{{result | json}}