How to display json data from api in tabular form? - angularjs

I am new to angular.I am trying to consume the data from api https://api.covid19india.org/travel_history.json. How to print the data from above api json data in tabular form? Is there any changes required? When the angular application is served the travel_history is to be in tabular form.
Here is the Component.ts
import { Component } from "#angular/core";
import { coronaApi } from "../service/service";
import { HttpErrorResponse } from "#angular/common/http";
#Component({
selector:'corona',
templateUrl:'./component.html'
})
export class CoronaComponent{
public result:Array<any>;
constructor(public service:coronaApi){}
ngOnInit(){
this.service.getData().subscribe((posRes)=>{
this.result=(posRes);
},(errRes:HttpErrorResponse)=>{
console.log(errRes)
})
}
}
Here is the component.html.
<table border="2">
<thead>
<tr>
<th colspan="11"> Travel History </th>
</tr>
<tr>
<th>_CN6CA</th>
<th>Accuracy Location</th>
<th>Address</th>
<th>Datasource</th>
<th>Latlong</th>
<th>Mode of Travel</th>
<th>Pid</th>
<th>Place Name</th>
<th>Time From</th>
<th>Time to</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let x of result";*ngFor = " let y of x ">
<td>{{y._cn6ca}}</td>
<td>{{y.accuracylocation}}</td>
<td>{{y.address}}</td>
<td>{{y.datasource}}</td>
<td>{{y.latlong}}</td>
<td>{{y.modeoftravel}}</td>
<td>{{y.pid}}</td>
<td>{{y.placename}}</td>
<td>{{y.timefrom}}</td>
<td>{{y.timeto}}</td>
<td>{{y.type}}</td>
</tr>
</tbody>
</table>

Hope this will work. While you are subscribing to getData() function you should use second loop.
this.result = response.travel_history;
Here are the component.ts
import { Component } from "#angular/core";
import { coronaApi } from "../service/service";
import { HttpErrorResponse } from "#angular/common/http";
#Component({
selector:'corona',
templateUrl:'./component.html'
})
export class CoronaComponent{
public result:Array<any>;
constructor(public service:coronaApi){}
ngOnInit(){
this.service.getData().subscribe((posRes)=>{
this.result=posRes.travel_history;
},(errRes:HttpErrorResponse)=>{
console.log(errRes)
})
}
}
Here are component.html
<tbody>
<tr *ngFor="let y of result">
<td>{{y._cn6ca}}</td>
<td>{{y.accuracylocation}}</td>
<td>{{y.address}}</td>
<td>{{y.datasource}}</td>
<td>{{y.latlong}}</td>
<td>{{y.modeoftravel}}</td>
<td>{{y.pid}}</td>
<td>{{y.placename}}</td>
<td>{{y.timefrom}}</td>
<td>{{y.timeto}}</td>
<td>{{y.type}}</td>
</tr>
</tbody>

On your ts file you add a boolean and display the data after the response. You don't need second loop just set
this.result = response.travel_history;
ts
isDataLoaded: boolean = false;
public result;
ngOnInit(){
this.service.getData().subscribe(response => {
this.result = response.travel_history;
this.isDataLoaded = true;
});
}
html
<tbody *ngIf="isDataLoaded">
<tr *ngFor="let x of result">
<td>{{x._cn6ca}}</td>
<td>{{x.accuracylocation}}</td>
<td>{{x.address}}</td>
<td>{{x.datasource}}</td>
<td>{{x.latlong}}</td>
<td>{{x.modeoftravel}}</td>
<td>{{x.pid}}</td>
<td>{{x.placename}}</td>
<td>{{x.timefrom}}</td>
<td>{{x.timeto}}</td>
<td>{{x.type}}</td>
</tr>
</tbody>

Related

Filtering donĀ“t work MatTableDataSource - Angular

I made a table with Angular Material, and used MatTableDataSource to filter the data from a search bar. However, although the column titles are rendered, my data is not displayed. Does anyone know what the problem is. I'm using Angular 13 with Json server for testing.
import { Component, OnInit } from '#angular/core';
import { MatTableDataSource } from '#angular/material/table';
import { Patient } from 'src/app/patients/model/patient';
import { PatientsService } from 'src/app/patients/patients.service';
#Component({
selector: 'app-search-bar',
templateUrl: './search-bar.component.html',
styleUrls: ['./search-bar.component.css']
})
export class SearchBarComponent implements OnInit {
patients: Patient[] = []
dataSource = new MatTableDataSource(this.patients)
displayedColumns = ["name", "cpf", "cityFrom", "surgeon"]
constructor(private patientsService: PatientsService) { }
ngOnInit(): void {
this.patientsService.read().subscribe(resp => {
this.patients = resp
})
}
applyFilter(filterValue: string) {
this.dataSource.filter = filterValue.trim().toLowerCase()
}
}
<form class="search-bar">
<mat-form-field class="example-full-width" appearance="fill">
<mat-label>Pesquisar</mat-label>
<span matPrefix class="material-icons icons">search</span>
<input (keyup)="applyFilter ($any($event.target).value)" matInput placeholder="Pesquisar" >
</mat-form-field>
</form>
<div class="div-table">
<table mat-table [dataSource]="dataSource" class="mat-elevation-z4 table">
Name Column
<ng-container matColumnDef="name">
<th class="table-title" mat-header-cell *matHeaderCellDef> Nome </th>
<td mat-cell *matCellDef="let row"> {{row.name}} </td>
</ng-container>
...
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
</div>

Each child in a list should have a unique "key" prop Error in React

Hi I am currently working with Spotify API with Spring Boot as the backend and React for the front end.
I was able to retrieve a user's favorite artist using the API in a json format but as I am not familiar with React, I am currently having problems displaying the data.
The json data that I have retrieved looks something like this.
[{"externalUrls":{"externalUrls":{"spotify":"https://open.spotify.com/artist/3dz0NnIZhtKKeXZxLOxCam"}},"followers":{"href":null,"total":929384},"genres":["complextro","edm","progressive electro house"],"href":"https://api.spotify.com/v1/artists/3dz0NnIZhtKKeXZxLOxCam","id":"3dz0NnIZhtKKeXZxLOxCam","images":[{"height":640,"url":"https://i.scdn.co/image/ab6761610000e5eb1804f56bdcb9322c5f3f8f21","width":640},{"height":320,"url":"https://i.scdn.co/image/ab676161000051741804f56bdcb9322c5f3f8f21","width":320},{"height":160,"url":"https://i.scdn.co/image/ab6761610000f1781804f56bdcb9322c5f3f8f21","width":160}],"name":"Porter Robinson","popularity":68,"type":"ARTIST","uri":"spotify:artist:3dz0NnIZhtKKeXZxLOxCam"},{"externalUrls":{"externalUrls":{"spotify":"https://open.spotify.com/artist/6M2wZ9GZgrQXHCFfjv46we"}},"followers":{"href":null,"total":27618208},"genres":["dance pop","pop","uk pop"],"href":"https://api.spotify.com/v1/artists/6M2wZ9GZgrQXHCFfjv46we","id":"6M2wZ9GZgrQXHCFfjv46we","images":[{"height":640,"url":"https://i.scdn.co/image/ab6761610000e5ebd42a27db3286b58553da8858","width":640},{"height":320,"url":"https://i.scdn.co/image/ab67616100005174d42a27db3286b58553da8858","width":320},{"height":160,"url":"https://i.scdn.co/image/ab6761610000f178d42a27db3286b58553da8858","width":160}],"name":"Dua Lipa","popularity":94,"type":"ARTIST","uri":"spotify:artist:6M2wZ9GZgrQXHCFfjv46we"}]
I am hoping to display this with React but seem to run into an error that reads
"Warning: Each child in a list should have a unique "key" prop."
My 'ListArtistComponent.jsx' file in my React application looks something like this.
class ListArtistComponent extends Component{
constructor(props) {
super(props);
this.state = {
artist: []
}
}
componentDidMount(){
ArtistService.getArtist().then((res) => {
this.setState({ artist: Array.from(res.data)});
});
}
render() {
return(
<div>
<h2 className="text-center">Artist List</h2>
<div className="row">
<table className="table table-striped table-bordered">
<thead>
<tr>
<th>Artist Name</th>
<th>Artist Popularity</th>
</tr>
</thead>
<tbody>
{
this.state.artist.map(
artist =>
<tr key = {artist.id}>
<td> {artist.name} </td>
<td> {artist.popularity} </td>
</tr>
)
}
</tbody>
</table>
</div>
</div>
)
}
}
export default ListArtistComponent;
And my ArtistService looks something like this
class ArtistService {
getArtist(){
return axios.get("http://localhost:8080/api/topartist")
}
}
export default new ArtistService()
I am guessing that a problem occurred when setting the 'id'(in the given json "3dz0NnIZhtKKeXZxLOxCam" and "6M2wZ9GZgrQXHCFfjv46we" respectively) value as the key, it would be appreciated if I could know what seems to be causing the problem and a solution for it.
Thank you in advance!!
I don't see any problem.
But if we use array index for the unique key.
can you try this?
class ListArtistComponent extends Component{
constructor(props) {
super(props);
this.state = {
artist: []
}
}
componentDidMount(){
ArtistService.getArtist().then((res) => {
this.setState({ artist: Array.from(res.data)});
});
}
render() {
return(
<div>
<h2 className="text-center">Artist List</h2>
<div className="row">
<table className="table table-striped table-bordered">
<thead>
<tr>
<th>Artist Name</th>
<th>Artist Popularity</th>
</tr>
</thead>
<tbody>
{
this.state.artist.map(
(artist,index) =>
<tr key = {index}>
<td> {artist.name} </td>
<td> {artist.popularity} </td>
</tr>
)
}
</tbody>
</table>
</div>
</div>
)
}

How to generate a table on select of a dropdown in Angular 8

In my program, I've the table already rendered with all the given possible values. I only want to retrieve the values matching with my bookingId in the table.
*view.component.ts
import { Component, OnInit } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs';
import { Booking } from '../booking.model';
import { ViewService } from './view.service';
#Component({
selector: 'app-view-component',
templateUrl: './view-component.component.html',
styleUrls: ['./view-component.component.css']
})
export class ViewComponentComponent implements OnInit {
bookings=[];
selected: number;
tableData:any[];
selectedId:string='';
constructor(private http: HttpClient, private view: ViewService) { }
ngOnInit(): void {
this.getBookings();
}
getBookings(): void {
this.view.getBookings()
.subscribe((data:any) => {
this.bookings = data;
console.log(this.bookings);
});
}
onSelected(value:string){
console.log("the selected value is " + value);
let temp =this.bookings.filter(el=>el.bookingId===value)
console.log(temp);
this.bookings=temp
}
}
view.component.html
<label for="bookings">
Select a Booking Id
</label>
<select class="form-control" id="bookings" #mySelect
(change)='onSelected(mySelect.value)'>
<option disabled selected value="">Select an Id</option>
<option *ngFor="let book of bookings" [value]="book.bookingId">
{{book.bookingId}}
</option>
</select>
<table class="table table-striped" >
<thead>
<tr>
<th>Booking Id</th>
<th>First Name</th>
<th>Gender</th>
<th>Category</th>
<th>Booking Date</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let book of bookings">
<td>{{book.bookingId}}</td>
<td>{{book.guestName}}</td>
<td>{{book.gender}}</td>
<td>{{book.categoryName}}</td>
<td>{{book.bookingDate| date: 'dd/MM/yyyy'}}</td>
</tr>
</tbody>
</table>
The problem is the table is already generated by the time my application loads. I want it to generate on select of the appropriate dropdown. The dropdown is populated by Booking Ids. Can someone give a solution
You binding same array in HTML use another empty array for filter data.
if you want first booking id data loaded when page render then just call onSelected(data[0].bookingId) after get data in getBookings()
filtersBookings = [];
onSelected(value:string){
this.filtersBookings =this.bookings.filter(el=>el.bookingId===value)
}
<tr *ngFor="let book of filtersBookings">
<td>{{book.bookingId}}</td>
<td>{{book.guestName}}</td>
<td>{{book.gender}}</td>
<td>{{book.categoryName}}</td>
<td>{{book.bookingDate| date: 'dd/MM/yyyy'}}</td>
</tr>
You should not load booking in ngOnInit hook, you should load it in your onSelected event handler,
and in your template, you can your the ngIf to load your table only when there is booking like the following
<table class="table table-striped" *ngIf="bookings.length>0">
<thead>
<tr>
<th>Booking Id</th>
<th>First Name</th>
<th>Gender</th>
<th>Category</th>
<th>Booking Date</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let book of bookings">
<td>{{book.bookingId}}</td>
<td>{{book.guestName}}</td>
<td>{{book.gender}}</td>
<td>{{book.categoryName}}</td>
<td>{{book.bookingDate| date: 'dd/MM/yyyy'}}</td>
</tr>
</tbody>
</table>

Render table when getting data asynchronous

I have some data which i get in state when componentDidMount.
I am trying render table using this data.
In my case rows not rendering.
How i can send data to tbody ?
export default class App extends Component {
constructor(props) {
super(props);
this.state={rows:null}
}
componentDidMount(){
var rows=[]
Meteor.http.call("GET", url ,function(error,result){
$.each(JSON.parse(result.content), function(key, value){
rows.push(value)
});
this.setState({
rows:rows});
})
}
renderRows(){
$.each(this.state.rows, function(d){
return(
<tr>
<td>{d[0]}</td>
<td>{d[1]}</td>
<td>{d[2]}</td>
<td>{d[3]}</td>
</tr>
)
})
}
render(){
return(
<Table>
<thead>
<tr>
<th>col1</th>
<th>col2</th>
<th>col3</th>
<th>col4</th>
</tr>
</thead>
<tbody>
{this.renderRows}
</tbody>
</Table>
)
}
}
Another option, not using JQuery and avoiding having a separate render function, is to use .map
React likes it if you have a unique key on each element in a list, so hopefully one of the fields on your row can serve this purpose.
render(){
return(
<Table>
<thead>
<tr>
<th>col1</th>
<th>col2</th>
<th>col3</th>
<th>col4</th>
</tr>
</thead>
<tbody>
{this.state.rows.map(d => (
<tr key={d[0]}>
<td>{d[0]}</td>
<td>{d[1]}</td>
<td>{d[2]}</td>
<td>{d[3]}</td>
</tr>
)}
</tbody>
</Table>
)
}
You'll also need to set your initial state for rows to be [] rather than null, in order for the first render to work.
renderRows is a function so you need to execute it. Also you will need to update that function a bit:
export default class App extends Component {
// ...
componentDidMount(){
var rows=[];
var self = this;
Meteor.http.call("GET", url ,function(error,result){
$.each(JSON.parse(result.content), function(key, value){
rows.push(value)
});
self.setState({
rows: rows
});
});
}
renderRows(){
const rows = this.state.rows || [];
return rows.map(d => {
return(
<tr>
<td>{d[0]}</td>
<td>{d[1]}</td>
<td>{d[2]}</td>
<td>{d[3]}</td>
</tr>
);
});
}
render(){
return(
<Table>
{/* ... */}
<tbody>
{this.renderRows()}
</tbody>
</Table>
)
}
}

Unable to figure out the async nature of the $http call

My controller/service retrieve the data from the url, and it returns with no errors. However, the repeat for the <tbody> doesn't show the data. The inspector shows no errors, and fiddler shows the url is called for the rest api.
Model
export interface IAuthor {
AuthorId: number;
FirstName: string;
LastName: string;
GoogleAuthorId: string;
CreatedByEmployeeId: any;
CreatedOn: Date;
ModifiedByEmployeeId: any;
ModifiedOn: Date;
PhotoURI: string;
}
Service
export class AuthorService implements IAuthorService {
private url: string;
static $inject = ["$http"];
constructor(private $http: ng.IHttpService) {
this.url = "/odata/Author";
}
getAuthors(): ng.IPromise<IAuthor[]> {
return this.$http
.get(this.url)
.then((response: ng.IHttpPromiseCallbackArg<IAuthor[]>): IAuthor[] => {
return response.data;
});
}
}
Controller
export class AuthorController implements IAuthorController {
authorItems: IAuthor[];
static $inject: string[] = ["AuthorService"];
constructor(private authorService: Services.IAuthorService) {
var results = this.getAuthors();
}
getAuthors(): IAuthor[] {
this.authorItems = [];
var results = this.authorService.getAuthors()
.then((authorItemsLocal: IAuthor[]): void => {
this.authorItems = authorItemsLocal;
});
return this.authorItems;
}
}
Html
<div class="container" ng-controller="AuthorController as vm">
<h2>Authors</h2>
<div>
<table class="table table-striped table-hover table-bordered">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Author ID</th>
</tr>
</thead>
<tbody ng-repeat="c in vm.authorItems">
<tr>
<td>{{ c.FirstName }}</td>
<td>{{ c.LastName }}</td>
<td>{{ c.AuthorId }}</td>
</tr>
</tbody>
</table>
</div>
</div>
I had typed the results to the proper type in typescript. When I typed them to "any", it worked.

Resources