How to read nested json array in Angular? - arrays

I have array from local json file test.json
{"collection":[{"scriptId":"28936862","startDate":"2020-03-31T15:54:45.658992","endDate":"2020-03-31T15:57:33.573312","createDate":"31.03.2020 15:54:45"}}]
So this is my app.component.ts
import { Component } from '#angular/core';
import tasksData from '../assets/test.json';
interface Task {
scriptId: String;
}
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
tasks: Task[] = tasksData;
}
This is my app.component.html
<div class="container">
<table class="table table-striped">
<thead>
<tr>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let task of tasks">
<td>{{ task.scriptId }}</td>
</tr>
</tbody>
</table>
The code above i took from here. In the example array is simple. But my array starts with "collection", and the code doesn't work.
My IDE gives an error on this line tasks: Task[] = tasksData;
How can I change the code for my json array?
Thank you in advance

Define tasks property like this :
tasks: Task[] = tasksData.collection;
and your interface should be like :
interface Task {
scriptId: string;
startDate: string;
endDate: string;
createDate: string;
}

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>

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>

How to display json data from api in tabular form?

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>

How to create a table in Angular based on a string value?

I'm using Angular 4/5 and I have to create several tables in the Angular based on a string value. Here is the model which I've made to create a table.
class NameValuePair {
Name: string;
Value: string;
}
export class Family {
Properties: Array<NameValuePair>;
PropertyType: string;
}
Given below is the hard-coded values which the table will contain.
export const list1: Family[] =
[
{
Properties: [
{
Name: "A",
Value: "1"
},
{
Name: "B",
Value: "2"
},
{
Name: "C",
Value: "3"
}
],
PropertyType: "Type 1"
},
{
Properties: [
{
Name: "A",
Value: "10"
},
{
Name: "B",
Value: "20"
},
{
Name: "C",
Value: "30"
}
],
PropertyType: "Type 1"
},
{
Properties: [
{
Name: "A",
Value: "100"
},
{
Name: "B",
Value: "200"
},
{
Name: "C",
Value: "300"
}
],
PropertyType: "Type 2"
}
]
Now, the main thing to note here is that the tables will be created based on the PropertyType. As in the above structure, the PropertyType of the first two elements of the array is same i.e. Type 1 so 2 tables will be created. One with the caption/heading: Type 1 and other with the caption: Type 2.
The properties[] array of the second array element will become the second row of the first table. I'm not able to find the logic on how do I create the tables based on this PropertyType string value. However, that's what I wrote in the component.html file but this logic is incorrect.
<div class="container pt-4" *ngFor="let element of list;let i = index">
<ng-container *ngIf="list[i].PropertyType == list[i+1].PropertyType">
<div style="padding-left:250px;font-size: 20px" class="pb-2">{{element.PropertyType}}</div>
<table id="{{element.PropertyType}}" class="table table-striped table-bordered table-responsive pb-3 mx-auto">
<thead style="height:40px">
<tr align="center">
<th *ngFor="let property of element.Properties" style="font-size: 20px">{{property.Name}}</th>
</tr>
</thead>
<ng-container *ngFor="let element1 of list">
<tr align="center" *ngIf="element.PropertyType == element1.PropertyType">
<td *ngFor="let property of element1.Properties; let propertyIndex = index" style="width: 200px">
<ng-container [ngSwitch]="propertyIndex">
<div *ngSwitchDefault style="font-size: 20px">{{property.Value}}</div>
</ng-container>
</td>
</tr>
</ng-container>
</table>
</ng-container>
</div>
list here refers to the list1 const array as mentioned above. Please help.
This is complete logic, I did not add css, since that is not asked. Use this it is working https://stackblitz.com/edit/angular-hd9jey
import {
Component
} from '#angular/core';
import {
list1
} from './list1';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
})
export class AppComponent {
tableArray = [];
constructor() {
let tableObject = {};
list1.forEach(i => {
if (tableObject[i.PropertyType]) {
tableObject[i.PropertyType].push(i);
} else {
tableObject[i.PropertyType] = [i];
}
this.tableArray = Object.entries(tableObject);
});
}
}
<div class="container pt-4" *ngFor="let table of tableArray;index as i">
<div style="padding-left:250px;font-size: 20px" class="pb-2">{{table[0]}}</div>
<table id="{{table[0]}}" class="table table-striped table-bordered table-responsive pb-3 mx-auto">
<thead style="height:40px">
<tr align="center">
<th *ngFor="let property of table[1][0].Properties" style="font-size: 20px">
{{property.Name}}</th>
</tr>
</thead>
<tr *ngFor="let property of table[1];" align="center">
<td *ngFor="let va of property.Properties">
{{va.Value}}
</td>
</tr>
</table>
</div>
You want to manipulate your list1 data into a nicer format first:
e.g.
export interface CustomTable {
header: string,
rows: Properties[]
}
const tables: CustomTable[] [];
list1.forEach(family => {
// Check if this type is already in the table.
const myTable: CustomTable = tables.find(customTable => customTable.header === family.propertyType);
if (myTable) {
// If it is, then add a new row
myTable.rows.push(family.Properties);
} else {
// If not, create a new table
myTable.rows.push({
header: family.propertyType,
rows: [family.Properties]
});
}
});
Then change your html accordingly. You probably want
<ng-container ngFor="let table of tables">
and within that somewhere a:
<tr *ngFor=let row of tables.rows>

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