How to bind Json response to table - json

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

Related

I'm trying to do a http get request to get data from my backend Larval, MYSQL I have created the API in Laravel but cant display the data in Angular

I'm new to programming and new advise please here is my code
employees component
import { DataService } from './../../service/data.service';
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-employees',
templateUrl: './employees.component.html',
styleUrls: ['./employees.component.css'
]})
export class EmployeesComponent implements OnInit {
employees: any
constructor(private dataservice: DataService) { }
ngOnInit() {
}
getEmployeesData() {
this.dataservice.getData().subscribe((res: any) => {
this.employees = res;
});
}
}
data.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class DataService {
getData: any;
constructor(private httpClient: HttpClient) {
this.httpClient.get('http://127.0.0.1:8000/api/employees')
};
}
HTML
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Surname</th>
<th scope="col">Email</th>
<th scope="col">Salary</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let emp of employees">
<th scope="row">{{emp.id}}</th>
<td>{{emp.name}}</td>
<td>{{emp.surname}}</td>
<td>{{emp.email}}</td>
<td>{{emp.salary}}</td>
</tr>
</tbody>
I see a couple of things, that cause the Data not to show up.
data.service.ts:
Your fetching the Data in the Constructor but you do ignore the return Value of your call. I suggest you do the call in a separate function that will be called if the data is needed.
constructor(private httpClient: HttpClient) {}
loadAllEmployees(): Observable<any> {
return this.httpClient.get('http://127.0.0.1:8000/api/employees');
}
Employees Component:
It seems, that you do not call the getEmployeesData function. Therefore your employees never get any Data.
employees: any
constructor(private dataservice: DataService) { }
ngOnInit() {
this.getEmployeesData();
}
getEmployeesData() {
this.dataservice.loadAllEmployees().subscribe((res: any) => {
this.employees = res;
});
}
With this setup, your data should load and be displayed.
Besides that, I would suggest you define the Type of the Employee and do not work with any. It does make it easier to read and understand your code. You are also less likely to get any Errors regarding types.

How to hide the full row if any cell value is null in angular

I would like to hide the row for the while payment due date cell is empty for the respective row.
while any value of Payment Due Date is null or empty I would like to hide the whole row respectively.
user.service.ts
import { Injectable } from '#angular/core';
import { HttpClient} from '#angular/common/http'
#Injectable({
providedIn: 'root'
})
export class UsersService {
constructor( private http:HttpClient) { }
getData(){
let url="https://Test.azurewebsites.net/api/accounts/getall";
return this.http.get(url);
}
}
app.component.ts
import { analyzeAndValidateNgModules } from '#angular/compiler';
import { Component } from '#angular/core';
import { UsersService} from './users.service'
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'coding-test';
data : any
constructor( private user:UsersService){
this.user.getData().subscribe(data=>{
console.warn(data)
this.data = data
})
}
}
app.component.html
<div class="jumbotron jumbotron-fluid">
<div class="container">
<h1 class="display-6">Display Sorted Account Info</h1>
<table class="table table-striped" >
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
<th >Amount Due</th>
<th>Payment Due Date</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of data" >
<td>{{item.LastName}},{{item.FirstName}}</td>
<td>{{item.Email}}</td>
<td>{{item.PhoneNumber | phone}}</td>
<td>{{item.AmountDue | currency}}</td>
<td>{{item.PaymentDueDate | date}}</td>
</tr>
</tbody>
</table>
</div>
</div>
on app.component.ts you can add filter by changing ((this.data = data )) to :
this.data = data.filter(x=>x.PaymentDueDate !== null );
Try to filter out the object based on the condition in your ts file.This will solve your problem.

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>

Carry data from dynamicaly generated table to the next page

Probably a noob question but I couldn't find an answer anywhere I searched. So basically I'm generating a table made of data I download from Firebase when the page is accessed, and I'd like the user to be able to click on one row of the table to access the precise details of the clicked element. It's kinda confusing to explain but it'll be much clearer with the code below.
Here is the BooksComponent typescript:
import { Component, OnInit } from '#angular/core';
import {AngularFirestore} from '#angular/fire/firestore';
import {Book} from '../../services/book';
#Component({
selector: 'app-books',
templateUrl: './books.component.html',
styleUrls: ['./books.component.css']
})
export class BooksComponent implements OnInit {
private books: Array<Book> = [];
constructor(private db: AngularFirestore) { }
ngOnInit() {
this.db.collection('books').get().subscribe((querySnapshot) => {
querySnapshot.forEach((doc) => {
this.books.push({
id: doc.id,
title: doc.get('title'),
writer: doc.get('writer'),
reserved: doc.get('reserved')
});
// console.log(doc.data());
});
});
}
}
And here is the associated HTML:
<div class="container d-flex min-vh-100 justify-content-center mt-5">
<table class="table table-bordered table-hover table-active">
<thead class="thead-dark">
<tr>
<th scope="col">Title</th>
<th scope="col">Writer</th>
<th scope="col">Reserved</th>
<!--<th scope="col">ID</th>-->
</tr>
</thead>
<tbody>
<!-- Here I'm putting on screen the array I populated back in the typescript, the [routerLink]=" [book.id]" seems to be working fine since in the detail page the id does update, everything else stays at 'dummy'-->
<tr *ngFor="let book of books;" [routerLink]="[book.id]" style="cursor: pointer">
<td>{{book.title}}</td>
<td>{{book.writer}}</td>
<td>{{book.reserved}}</td>
<!--<td>{{book.id}}</td>-->
</tr>
</tbody>
</table>
</div>
Now here is the BookDetailComponent typescript:
import { Component, OnInit } from '#angular/core';
import {Book} from '../../services/book';
import {ActivatedRoute} from '#angular/router';
#Component({
selector: 'app-book-detail',
templateUrl: './book-detail.component.html',
styleUrls: ['./book-detail.component.css']
})
export class BookDetailComponent implements OnInit {
private book: Book = {
id: 'dummy',
title: 'dummy',
writer: 'dummy',
reserved: 'dummy'
};
constructor(private route: ActivatedRoute) { }
ngOnInit() {
this.book.id = this.route.snapshot.params.id;
}
}
I managed to update the 'id' field according to which row the user clicked on, it's also correctly updated in the Web Page URL, but that's about it. I'm thinking I could search and retrieve informations corresponding to the id in the Array that stores all the books but I'm not sure how to do that excatly. Any advice/help is greatly appreciated.
So technically for the list, you should have an API and for the individual id route also you should have another API which gives you more details. But since, you don't have such an API that gives details based on id, you could make use of a service.I would not recommend this, but it will work. When you click on a book, update a service function with the index and get the corresponding details in bookdetail component.
bookArr: Array<object>
setBookDetails(arr) {
this.bookArr = arr;
}
updateIndex(idx) {
this.detailIdx = idx;
}
getDetails(){
return this.bookArr[this.detailIdx]
}

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>
...