Put json data into table - json

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.

Related

angular api datatable : no data found

I'm trying to make a table with this API:
https://run.mocky.io/v3/70e5b0ad-7112-41c5-853e-b382a39e65b7/people
the html structure of my table appears but not the data of my API and I have no error in the console
Do you have a solution ?
here is the structure of my rest component (code of my table):
people.ts
export class people {
id: string;
firstname: string;
lastname: string;
email: string;
mobile: string;
city: string;
country: string;
constructor(id,firstName,lastName,email,mobile,city,country){
this.id=id;
this.firstname=firstName;
this.lastname=lastName;
this.email=email;
this.mobile=mobile;
this.city=city;
this.country=country;
}
}
rest.component.html
<h1>Employee Dashboard</h1>
<table class="table table-bordered">
<thead>
<tr>
<th>Id</th>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
<th>Address</th>
<th>City</th>
<th>Country</th>
</tr>
</thead>
<tbody>
<tr *ngFor= "let user of users">
<td>{{people.id}}</td>
<td>{{people.firstname}}</td>
<td>{{people.lastname}}</td>
<td>{{people.email}}</td>
<td>{{people.address}}</td>
<td>{{people.city}}</td>
<td>{{people.country}}</td>
</tr>
</tbody>
</table>
rest.component.spec.ts
import { TestBed, async } from '#angular/core/testing';
import { RouterTestingModule } from '#angular/router/testing';
import { AppComponent } from './rest.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule
],
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
});
it(`should have as title 'project'`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('project');
});
it('should render title in a h1 tag', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('Welcome to project!');
});
});
rest.component.ts
import { Component, OnInit } from '#angular/core';
import { people } from './people';
import { RestService } from './rest.service';
#Component({
selector: 'app-root',
templateUrl: './rest.component.html',
styleUrls: ['./rest.component.css']
})
export class RestComponent implements OnInit {
people: people[] = [];
constructor(public rs: RestService){
}
ngOnInit():void {
this.rs.getUsers().subscribe((response) => {
this.people=response;
})
}
title = 'project';
}
rest.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { people } from './people'
#Injectable({
providedIn: 'root'
})
export class RestService {
constructor(private http:HttpClient){}
url:string= "https://run.mocky.io/v3/70e5b0ad-7112-41c5-853e-b382a39e65b7/people";
getUsers(){
return this.http.get<people[]>(this.url);
}
}
The actual array of People objects is under a property named "people" in the API response. So, modify the service code:
getUsers(){
return this.http.get<any>(this.url).pipe(
map(response) => {
return response['people'];
})
);
}
The code you will need to change will be in two files
rest.component.html
Replace this
<tr *ngFor= "let user of users">
<td>{{people.id}}</td>
<td>{{people.firstname}}</td>
<td>{{people.lastname}}</td>
<td>{{people.email}}</td>
<td>{{people.address}}</td>
<td>{{people.city}}</td>
<td>{{people.country}}</td>
</tr>
with this
<tr *ngFor= "let user of users">
<td>{{user.id}}</td>
<td>{{user.firstname}}</td>
<td>{{user.lastname}}</td>
<td>{{user.email}}</td>
<td>{{user.address}}</td>
<td>{{user.city}}</td>
<td>{{user.country}}</td>
</tr>
In rest.component.ts
Replace
ngOnInit():void {
this.rs.getUsers().subscribe((response) => {
this.people=response;
})
with this
ngOnInit():void {
this.rs.getUsers().subscribe((response) => {
this.users=response.people;
})
It should be user.id not people.id
<tr *ngFor= "let user of users">
<td>{{user.id}}</td>
<td>{{user.firstname}}</td>
<td>{{user.lastname}}</td>
<td>{{user.email}}</td>
<td>{{user.address}}</td>
<td>{{user.city}}</td>
<td>{{user.country}}</td>
</tr>
The problem with code is you saving data in people and in frontend you are using user which is not defined.
<tbody>
<tr *ngFor= "let p of people">
<td>{{p.id}}</td>
<td>{{p.firstname}}</td>
<td>{{p.lastname}}</td>
<td>{{p.email}}</td>
<td>{{p.address}}</td>
<td>{{p.city}}</td>
<td>{{p.country}}</td>
</tr>
</tbody>

How to print JSON values with keys starting with special characters using angular?

When I try to print using #place it throws error while the other keys are accessible.
[{
"ID": "001",
"Name": "Eurasian Collared-Dove",
"Type": "Dove",
"Scientific Name": "Streptopelia",
"#place": "New York"
}]
This is the error I am getting:
Parser Error: Unexpected token Lexer Error: Unexpected character [#] at column 6 in expression [bird.#place], expected identifier or keyword at column 7 in [{{bird.#place}}]
The component.ts file is as follows:
import { Component } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { HttpErrorResponse } from '#angular/common/http';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'JSON to Table ';
constructor (private httpService: HttpClient) { }
arrBirds: string [];
ngOnInit () {
this.httpService.get('./assets/birds.json').subscribe(
data => {
this.arrBirds = data as string []; // FILL THE ARRAY WITH DATA.
// this.arrService = JSON.stringify(data);
console.log(this.arrBirds);
},
(err: HttpErrorResponse) => {
console.log (err.message);
}
);
}
}
The component.html file is like this:
<table *ngIf="arrBirds">
<tr>
<th>ID</th>
<th>Name of Bird</th>
<th>Type of Bird</th>
<th>Place</th>
</tr>
<tr *ngFor="let bird of arrBirds">
<td>{{bird.ID}}</td>
<td>{{bird.Name}}</td>
<td>{{bird.Type}}</td>
<td>{{bird.#place}}</td>
</tr>
</table>
As noted in my comment, you could use the bracket notation instead of the dot notation.
<tr *ngFor="let bird of arrBirds">
<td>{{ bird['ID'] }}</td>
<td>{{ bird['Name'] }}</td>
<td>{{ bird['Type'] }}</td>
<td>{{ bird['#place'] }}</td>
</tr>
Working example: Stackblitz
In HTML I don't know any other method to call a property. The only solution I can see is to do a getter.
In TS
get place() {
return bird['#Place']
}
In HTML
{{ place }}

How to bind Json response to table

I have products.components.ts class, where I am getting Json data in this.Getdata
ngOnInit() {
this._service.getProducts(this.baseUrl)
.subscribe(data => {
this.Getdata=data
this.products=data
alert(JSON.stringify(this.Getdata));
});
This Josn data I want to bind in products.components.html class Table
<p>
Product List
</p>
<table>
<th>Id</th> <th>Name</th> <th> Country</th> <th>Actions</th>
<tr *ngFor="let lst of products; let i = index" border="1">
<td>{{i+1}}</td><td>{{lst.id}}</td><td>{{lst.employee_name}}</td> <td>Edit</td>
</tr>
</table>
The above code is not working. Only alert displaying. How can I bind data to table?
This is my Json data
[{"id":"1","employee_name":"amit","employee_salary":"0","employee_age":"0","profile_image":""},{"id":"247793","employee_name":"Ana","employee_salary":"123","employee_age":"123","profile_image":""},{"id":"247856","employee_name":"Joseph Beltran","employee_salary":"1000","employee_age":"23","profile_image":""},{"id":"247982","employee_name":"testyeyyeye1","employee_salary":"123","employee_age":"23","profile_image":""},{"id":"248007","employee_name":"test100","employee_salary":"123","employee_age":"23","profile_image":""},{"id":"248038","employee_name":"Hendry","employee_salary":"61888","employee_age":"26","profile_image":""}]
Model class
export class Productlist {
id: string;
employee_name: string;
employee_salary: string;
employee_age: string;
profile_image: string;
}
Instead of subscribing to the Observable, consider storing it in a property and then unwrapping it in the template using the async pipe.
If you consider that, then you can significantly reduce your Component to this:
import { Component } from '#angular/core';
import { Observable } from 'rxjs';
import { EmployeeService } from './employee.service';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
employees$: Observable<Array<any>> = this.employeeService.getEmployees();
constructor(private employeeService: EmployeeService) {}
}
And in your Template:
<p>
Employee List
</p>
<table border="1">
<thead>
<th>Id</th>
<th>Name</th>
<th> Country</th>
<th>Actions</th>
</thead>
<tbody>
<tr *ngFor="let employee of employees$ | async; let i = index">
<td>{{i+1}}</td>
<td>{{employee.id}}</td>
<td>{{employee.employee_name}}</td>
<td>Edit</td>
</tr>
</tbody>
</table>
Here's a Working Sample Demo Code for your ref.
PS: Consider naming your properties and methods appropriately. If you're working with employees, then it doesn't really make sense to name properties and methods as products.
You can also use
const myobject= JSON.parse(yourjsonvalue);
You will get the object in myobject and now you can loop through with simple ngFor.
I got it this way
export class ProductsComponent implements OnInit {
public Getdata;
products:Productlist[];
constructor(private employeeService: ProductService) {}
ngOnInit() {
this.employeeService.getProducts(this.baseUrl)
.subscribe((data:any) => {
this.products=data;
});
}
}

Angular 8 - HttpClient GET a complex JSON object and fill an html table

I am using Angular 8, and am querying an endpoint to get an object. When I call it via Advanced REST Client, I get the following returned JSON:
GET: http://localhost:8090/curso_conductor/
Returns:
{
"dato": [{
"ID_CURSO_CONDUCTOR": 1,
"F_INICIO": "2019-09-19T05:00:00.000+0000",
"F_FIN": "2019-12-20T05:00:00.000+0000",
"ESTADO": "1",
"CARNET_C": "l584f",
"F_CADUCIDAD": "2022-06-20T05:00:00.000+0000",
"F_EMISION": "2017-06-20T05:00:00.000+0000",
"ID_CURSO": 1,
"ID_PERSONA": 3
},
{
"ID_CURSO_CONDUCTOR": 2,
"F_INICIO": "2019-08-20T05:00:00.000+0000",
"F_FIN": "2019-12-20T05:00:00.000+0000",
"ESTADO": "1",
"CARNET_C": "8574h",
"F_CADUCIDAD": "2023-04-05T05:00:00.000+0000",
"F_EMISION": "2017-04-08T05:00:00.000+0000",
"ID_CURSO": 1,
"ID_PERSONA": 5
},
{
"ID_CURSO_CONDUCTOR": 3,
"F_INICIO": "2019-10-09T05:00:00.000+0000",
"F_FIN": "2019-12-10T05:00:00.000+0000",
"ESTADO": "1",
"CARNET_C": "2685f",
"F_CADUCIDAD": "2022-08-10T05:00:00.000+0000",
"F_EMISION": "2017-08-09T05:00:00.000+0000",
"ID_CURSO": 1,
"ID_PERSONA": 6
}
],
}
In Angular 8, I then have a service, where I want to make an http call to to the endpoint that will return the above JSON.
getCursoConductor(): Observable<Curso_Conductor[]>{
return this.http.get<Curso_Conductor[]>(this.curso_conductores).pipe();
}
As you can see the result needs to be put into the Curso_Conductor object.
And my model is this:
export class Curso_Conductor {
dato: Dato[];
}
export class Dato {
ID_CURSO_CONDUCTOR: number;
F_INICIO: string;
F_FIN: string;
ESTADO: string;
CARNET_C: string;
F_CADUCIDAD: string;
F_EMISION: string;
ID_CURSO: number;
ID_PERSONA: number;
}
My question is how do I put the data into the Curso_conductorComponent.html?
This is my component.html:
<table class="table table-hover">
<thead>
<tr>
<th>ID</th>
<th>FECHA INICIO</th>
<th>FECHA FIN</th>
<th>ESTADO</th>
<th>Nro CARNET</th>
<th>FECHA CADUCIDAD</th>
<th>FECHA EMISION</th>
<th>IDCURSO</th>
<th>IDPERSONA</th>
<th colspan="2">OPCION</th>
</tr>
</thead>
<tbody>
<tr *ngIf="curso_conductoresObservable | async as curso_conductores else empty">
<tr *ngFor="let curso_conductor of curso_conductores">
<td>{{curso_conductor.id_curso_conductor}}</td>
<td>{{curso_conductor.f_inicio}}</td>
<td>{{curso_conductor.f_fin}}</td>
<td>{{curso_conductor.estado}}</td>
<td>{{curso_conductor.carnet_c}}</td>
<td>{{curso_conductor.f_caducidad}}</td>
<td>{{curso_conductor.f_emision}}</td>
<td>{{curso_conductor.id_curso}}</td>
<td>{{curso_conductor.id_persona}}</td>
<td><button class="btn btn-warning" (click)="Editar(curso_conductor)">Editar</button></td>
<td><button class="btn btn-danger" (click)="Eliminar(curso_conductor)">Eliminar</button></td>
</tr>
</tbody>
</table>
And my component.ts:
curso_conductores: Curso_Conductor[];
constructor(private service: ServiceService, private router: Router) { }
#Input() nombre = '';
ngOnInit() {
this.service.getCursoConductor()
.subscribe(data => {this.curso_conductores=data });
}
I'm getting this error:
Cannot find a differ supporting object
'[object Object]' of type 'object'. NgFor only supports binding to
Iterables such as Arrays.
There are a few issue with your implementation.
The array that you get from the API is present on the dato property. You ideally you should be creating an interface for that:
export interface ApiResponse {
dato: Curso_Conductor[];
}
export interface Curso_Conductor {
ID_CURSO_CONDUCTOR: number;
F_INICIO: string;
F_FIN: string;
ESTADO: string;
CARNET_C: string;
F_CADUCIDAD: string;
F_EMISION: string;
ID_CURSO: number;
ID_PERSONA: number;
}
You'll then have to update your service to reflect the type of data that you're expecting. I'm also changing the name of the service as ServiceService makes no sense at all:
import { Injectable } from "#angular/core";
import { HttpClient } from "#angular/common/http";
import { Observable } from "rxjs";
import { ApiResponse } from "./models/conductor.model";
#Injectable()
export class DataService {
curso_conductores = "assets/data.json";
constructor(private http: HttpClient) {}
getCursoConductor(): Observable<ApiResponse> {
return this.http.get<ApiResponse>(this.curso_conductores);
}
}
You're subscribeing to the Observable in your Component and you're also using an async pipe. Which automatically does the unwrapping for you. So just stick to using the async pipe in the template. That's also what's the recommended way:
import { Component } from "#angular/core";
import { Curso_Conductor, ApiResponse } from "./models/conductors.model";
import { DataService } from "./data.service";
import { Observable } from "rxjs";
import { map } from "rxjs/operators";
#Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
curso_conductores$: Observable<Array<Curso_Conductor>>;
constructor(private service: DataService) {}
ngOnInit() {
this.curso_conductores$ = this.service.getCursoConductor()
.pipe(
map((apiResponse: ApiResponse) => apiResponse.dato)
);
}
}
Finally, the Object fields are all in upper case but you're using them as lower case in the template. That needs to be fixed as well:
<table class="table table-hover" border="1">
<thead>
<tr>
<th>ID</th>
<th>FECHA INICIO</th>
<th>FECHA FIN</th>
<th>ESTADO</th>
<th>Nro CARNET</th>
<th>FECHA CADUCIDAD</th>
<th>FECHA EMISION</th>
<th>IDCURSO</th>
<th>IDPERSONA</th>
<th colspan="2">OPCION</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let curso_conductor of (curso_conductores$ | async) as curso_conductores">
<td>{{curso_conductor.ID_CURSO_CONDUCTOR}}</td>
<td>{{curso_conductor.F_INICIO}}</td>
<td>{{curso_conductor.F_FIN}}</td>
<td>{{curso_conductor.ESTADO}}</td>
<td>{{curso_conductor.CARNET_C}}</td>
<td>{{curso_conductor.F_CADUCIDAD}}</td>
<td>{{curso_conductor.F_EMISION}}</td>
<td>{{curso_conductor.ID_CURSO}}</td>
<td>{{curso_conductor.ID_PERSONA}}</td>
<td><button class="btn btn-warning" (click)="Editar(curso_conductor)">Editar</button></td>
<td><button class="btn btn-danger" (click)="Eliminar(curso_conductor)">Eliminar</button></td>
</tr>
</tbody>
</table>
Hope this clears this up for you.
Here's a Working Sample StackBlitz for your ref.
Are you sure the return type is Curso_Conductor[]? It seems like Curso_Conductor.
Try this,
getCursoConductor(): Observable<Curso_Conductor>{
return this.http.get<Curso_Conductor>(this.curso_conductores).pipe();
}
...
curso_conductore: Curso_Conductor;
constructor(private service: ServiceService, private router: Router) { }
#Input() nombre = '';
ngOnInit() {
this.service.getCursoConductor().subscribe(data => {this.curso_conductore=data });
}
and in html
...
<tr *ngFor="let d of curso_conductore.dato.dato">
<td>{{d.id_curso_conductor}}</td>
<td>{{d.f_inicio}}</td>
...

Angular dynamic table using ngFor

I would like to know if it is possible to create a dynamic HTML table from JSON data. The amount of columns and headers should change according to the keys in the JSON. For example this JSON should create this table:
{
color: "green", code: "#JSH810"
}
,
{
color: "red", code: "#HF59LD"
}
...
And this JSON should create this table:
{
id: "1", type: "bus", make: "VW", color: "white"
}
,
{
id: "2", type: "taxi", make: "BMW", color: "blue"
}
...
This has to be 100% dynamic though, because I want to display hundreds of different JSON objects, so nothing should be hard coded in the HTML page.
If you want to get the key of your object as the head of your table, you should create a custom pipe.
import { PipeTransform, Pipe } from '#angular/core';
#Pipe({name: 'keys'})
export class KeysPipe implements PipeTransform {
transform(value, args:string[]) : any {
let keys = [];
for (let key in value) {
keys.push(key);
}
return keys;
}
}
Update: Or simply return keys using Object.keys().
(demo)
#Pipe({name: 'keys'})
export class KeysPipe implements PipeTransform {
transform(value, args:string[]) : any {
return Object.keys(value);
}
}
Now into your html template:
<table>
<thead>
<tr>
<th *ngFor="let head of items[0] | keys">{{head}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of items">
<td *ngFor="let list of item | keys">{{item[list]}}</td>
</tr>
</tbody>
</table>
Update: Here is the demo.
This can help:
export class AppComponent {
//Array of any value
jsonData:any = [
{id: "1", type: "bus", make: "VW", color: "white"},
{id: "2", type: "taxi", make: "BMW", color: "blue"}
];
_object = Object;
}
<div>
<table border="1">
<thead>
<tr>
<th *ngFor="let header of _object.keys(jsonData[0]); let i = index">{{header}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of jsonData; let i = index">
<th *ngFor="let objKey of _object.keys(row); let j = index">{{ row[objKey] }} </th>
</tr>
</tbody>
</table>
</div>