when fetching json array object from rest api and trying to display in ngfor failed with the reason
error
EXCEPTION: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays. in [indexes in HomeComponent#5:37]
Code
import {Component} from 'angular2/core';
import {HomeService} from './home.services';
import {Index} from './index';
#Component({
selector: 'home-app',
providers: [HomeService],
template: `
<section class="left_side">
<article>
<div class="div_home">
<div class="div_homeIndxPartition">
<div class="div_IndxPartition" *ngFor="#indObj of indexes">
<table width="500px" class="idx_cons_table_det">
<tr>
<th align="center" color="#A9F5F2"><h3>{{indObj.name}} ({{indObj.tracker}})</h3></th>
<th align="center">Value</th>
<th align="center">Change</th>
<th align="center">%</th>
</tr>
<tr>
<td align="center" colspan="1"></td>
<td align="center">{{indObj.value}}</td>
<td align="center">{{indObj.change}}</td>
<td align="center">{{indObj.percent}}%</td>
</tr>
</table>
<br/>
<table width="500px" class="idx_cons_table">
<tr>
<th align="center">High</th>
<th align="center">Low</th>
<th align="center">Open</th>
<th align="center">Close</th>
<th align="center">52 Week High</th>
<th align="center">52 Week Low</th>
</tr>
<tr>
<td align="center">{{indObj.high}}</td>
<td align="center">{{indObj.low}}</td>
<td align="center">{{indObj.open}}%</td>
<td align="center">{{indObj.close}}</td>
<td align="center">{{indObj.yearHigh}}</td>
<td align="center">{{indObj.yearLow}}%</td>
</tr>
</table>
</div>
</div>
</div>
</article>
</section>
`
})
export class HomeComponent {
public indexes:Array<Index>=[];
public error;
constructor(private _service: HomeService){
this.indexes = _service.getIndexes().subscribe(
data => this.indexes = JSON.parse(data),
error => alert(" Error is : " + error),
()=> console.log("finished")
);
console.log(this.indexes);
}
}
JSON Data
[
{
"id": 1,
"name": "FTSE 100",
"ticker": "UKX",
"value": 69875.23,
"change": 100,
"percent": 2.3,
"high": 69875.23,
"low": 69700.89,
"yearHigh": 699999.23,
"yearLow": 680005.23,
"open": 69600.54,
"close": 699000.97,
"constituents": null,
"runDate": "21/04/2015"
},
{
"id": 2,
"name": "FTSE 250",
"ticker": "MCX",
"value": 465820.85,
"change": 100,
"percent": 2.3,
"high": 465880.12,
"low": 465810.74,
"yearHigh": 478990.34,
"yearLow": 465320.23,
"open": 69600.54,
"close": 699000.97,
"constituents": null,
"runDate": "21/04/2015"
},
{
"id": 3,
"name": "FTSE All-Share",
"ticker": "ASX",
"value": 236549.23,
"change": 100,
"percent": 2.3,
"high": 236949.23,
"low": 236149,
"yearHigh": 246949.21,
"yearLow": 235549.29,
"open": 236519.23,
"close": 236649.23,
"constituents": null,
"runDate": "21/04/2015"
},
{
"id": 4,
"name": "Euro Stoxx 50",
"ticker": "STOXX50E",
"value": 123469.87,
"change": 100,
"percent": 2.3,
"high": 123499.87,
"low": 123439.87,
"yearHigh": 123499.87,
"yearLow": 123169.87,
"open": 123465.87,
"close": 123459.87,
"constituents": null,
"runDate": "21/04/2015"
},
{
"id": 5,
"name": "S&P 500 ",
"ticker": "S500",
"value": 358976.36,
"change": 100,
"percent": 2.3,
"high": 358986.36,
"low": 358946.36,
"yearHigh": 359976.36,
"yearLow": 357976.36,
"open": 358970.36,
"close": 358996.36,
"constituents": null,
"runDate": "21/04/2015"
},
{
"id": 6,
"name": "Dow Jones I.A.",
"ticker": "INDU",
"value": 456789.36,
"change": 100,
"percent": 2.3,
"high": 456799.36,
"low": 456779.36,
"yearHigh": 456889.36,
"yearLow": 456689.36,
"open": 456729.36,
"close": 456779.36,
"constituents": null,
"runDate": "21/04/2015"
},
{
"id": 7,
"name": "GOLD",
"ticker": "",
"value": 500,
"change": 100,
"percent": 2.3,
"high": 700,
"low": 300,
"yearHigh": 1500,
"yearLow": 350,
"open": 450,
"close": 470,
"constituents": null,
"runDate": "21/04/2015"
},
{
"id": 8,
"name": "Brent Crude",
"ticker": "",
"value": 112,
"change": 100,
"percent": 2.3,
"high": 115,
"low": 107,
"yearHigh": 200,
"yearLow": 72,
"open": 110,
"close": 115,
"constituents": null,
"runDate": "21/04/2015"
}
]
I think that the value you set in the indexes property isn't an array but an object.
I would see several reasons for this:
You receive the response instead of the payload from the getIndexes method. In this case, you could use the map operator in this method:
getIndexes() {
return this.http.get(...).map(res => res.json());
}
The received payload doesn't correspond to an array but some of its properties. In this case, you need to set this property into the indexes property.
If you want to iterate over the properties of an object, you need to implement a custom filter like this:
#Pipe({name: 'keyValues'})
export class KeysPipe implements PipeTransform {
transform(value, args:string[]) : any {
let keys = [];
for (let key in value) {
keys.push({key: key, value: value[key]);
}
return keys;
}
}
and use it like that:
<div class="div_IndxPartition" *ngFor="#indObj of indexes | keyValues">
(...)
</div>
See this question:
How to display json object using *ngFor
You should try this:
In html:
<div *ngFor="let subsciption of subscriptions;">
<div class="col-md-6">
<h5 class="widget-title">{{subsciption.name}}</h5>
</div>
</div>
in .ts file:
export class SubscriptionComponent implements OnInit {
private subscriptions: any =[];
// private subscriptions: any ={}; // here dont use {}
.
.
.
.
.
getAllSubscriptions(queryString) {
this._http.get(`${environment.base_url}/subscriptions` + queryString)
.subscribe((response: Response) => {
this.subscriptions = response.json();
},
(error: Response) => {
console.log("Login error");
});
}
this.getAllSubscriptions(query);
}
I had same problem and my solution was without Pipes. I did not use variable in the template that returns Observer, create intermediate variable and assign result to it. For example, we will save stream to this.sub but result will save to this.indexes on success callback and will use this variable in the html template.
#Component({
template: `
<ul>
<li *ngFor="let index of indexs">
{{ index }}
</li>
</ul>
`
})
export class HomeComponent {
privat sub;
public indexes:Array<Index>=[];
public error;
constructor(private _service: HomeService) {
this.sub = this._service.getIndexes().subscribe(
data => this.indexes = JSON.parse(data),
error => alert(" Error is : " + error),
() => console.log("finished")
);
}
}
You don't want to use pipes when working with Observables.
This error is very generic and the best way is to throw in a console.log() and see where you are going wrong as it could be numerous things.
My problem was my Array was inside the Object, and I was trying to loop over the Object. Other problems could include the mapping or the ngFor. My console output would look something like this:
this.indexes = _service.getIndexes()
.subscribe(
data => {
this.indexes = JSON.parse(data);
console.log(indexes);
},
error => alert(" Error is : " + error),
()=> console.log("finished")
);
console.log(this.indexes);
So the fix I needed was something like this:
this.indexes = _service.getIndexes()
.subscribe(
data => {
this.myNewObject = JSON.parse(data);
this.indexes = this.myNewObject.indexes;
},
error => alert(" Error is : " + error),
()=> console.log("finished")
);
console.log(this.indexes);
This was because the array was nested inside the Object, so I just created a new object and accessed the array by getting its property.
i see your answer, and the easy way to solve is just set the type of the object in the *ngFor to array like this:
public indexes:Array<TYPE_OF_YOUR_DATA>=[];
Related
I am a beginner and I try to create a dynamic pie chart using angular and Kendo UI. I want to get data from json file and it is located inside the assets folder. I tried to link the .ts file and json file. but the chart does not show.
This is my component.html file
<kendo-chart [transitions]="false" [style.height]="'100%'" [style.width]="'100%'">
<kendo-chart-series>
<kendo-chart-series-item type="pie"
[data]="data"
categoryField="kind"
field="share"
[autoFit]="true"
*ngIf="data">
<kendo-chart-series-item-labels [align]="labelAlign"
color="#000"
[content]="labelContent">
</kendo-chart-series-item-labels>
</kendo-chart-series-item>
</kendo-chart-series>
<kendo-chart-legend [visible]="false"></kendo-chart-legend>
</kendo-chart>
This is my db.json file
{"data": [
{
"id": 1,
"kind": "Solar",
"share": 5
},
{
"id": 2,
"kind": "Wind",
"share": 2
},
{
"id": 3,
"kind": "Geothermal",
"share": 1
},
{
"id": 4,
"kind": "Natural Gas",
"share": 1
},
{
"id": 5,
"kind": "Coal",
"share": 80
},
{
"id": 6,
"kind": "Hydroelectric",
"share": 2
},
{
"id": 7,
"kind": "Nuclear",
"share": 2
},
{
"id": 8,
"kind": "Other",
"share": 1
}
]
}
This is my component.ts file
data = null;
constructor(private http: HttpClient) {}
ngOnInit() {
this.http.get('assets/db.json').subscribe(
data => this.data = data,
err => console.error('File is missing: ', err),
);
}
public labelContent(e: any): string {
return e.category;
}
}
Try to modify the data you pass into <kendo-chart-series-item> tag to be like that [data]="data?.data", as [data] should be in the form of an array of objects, and your array of objects is the value of the key data in your json file.
I have json object like this:
{
"cartId": 1,
"cartName": "Cart",
"CartItems": [
{
"productId": 1,
"product": {
"productId": 1,
"productName": "milk",
"price": 3.0,
"categoryId": 1,
},
"price": 3.0,
"quantity": 4,
"subTotal": 12.0
},
{
"productId": 2,
"product": {
"productId": 2,
"productName": "oranges",
"price": 3.0,
"categoryId": 5,
},
"price": 3.0,
"quantity": 6,
"subTotal": 18.0
}
],
"grandTotal": 30.0
}
this is my service:
getCart(): Observable<Cart[]> {
return this.http.get<Cart[]>(this.myAppUrl + this.myApiUrl)
.pipe(
retry(1)
);
}
this is my component:
cart$: Observable<Cart[]>;
constructor(private cart_Service: CartService,private http: HttpClient) {
}
ngOnInit() {
this.loadCart();
}
loadCart() {
this.cart$ = this.cart_Service.getCart();
}
I want to catch grandTotal like this in cart.component.html file:
<p *ngIf="!(cart$ | async)"><em></em></p>
<table class="table table-sm table-hover" >
<thead>
<tr>
<th> Grand Total</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let i of (cart$ | async)">
<td>{{ i.grandTotal }}</td>
</tr>
</tbody>
but I get error saying that " NgFor only supports binding to Iterables such as Arrays."
I tried different solutions to convert my json object to typescript array but none of them were helpful.
Can someone please help me to catch grandTotal and show it with html in my web api. I think we should have array to be able to get that grandTotal.
You can try either this
return this.http.get<Cart[]>(this.myAppUrl + this.myApiUrl)
.pipe(
map(response => response as unknows as Cart[])
retry(1)
);
OR
map the response as Cart[]
I finally could solve this. This is my service
getCart(): Observable<Cart[]> {
return this.http.get<Cart[]>(this.myAppUrl + this.myApiUrl);
}
this is my component:
my_data: any;
public loadCart() {
this.cart_Service.getCart().subscribe((data: Cart[]) => this.my_data = data);
}
this is my HTML:
<div>
<p> Grand Total : {{ my_data.grandTotal }} </p>
</div>
I am trying to get data from a JSON file in ionic app using.
this.http.get('https://track.delhivery.com/api/packages/json/?token=c7ac81cde31a5ea69d38cb098cab16cf7f909062&waybill=2285210000022').map(res => res.json()).subscribe(data => {
this.trackingorder = data;
console.log(this.trackingorder.ShipmentData);
But i am getting error that Shipment is undefined.
My JSON file is of the format
{
"ShipmentData": [
{
"Shipment": {
"Origin": "Bengaluru_Bomsndra_PC (Karnataka)",
"Status": {
"Status": "Delivered",
"StatusLocation": "Cjb_Kovaipudur_Dc (Tamil Nadu)",
"StatusDateTime": "2018-12-20T17:57:28.002000",
"RecievedBy": "",
"Instructions": "Delivered to consignee",
"StatusType": "DL",
"StatusCode": "EOD-38"
},
"PickUpDate": "2018-12-18T19:44:43",
"ChargedWeight": null,
"OrderType": "Pre-paid",
"Destination": "Coimbatore",
"Consignee": {
"City": "Coimbatore",
"Name": "Sayal Krishna",
"Country": "India",
"Address2": [],
"Address3": "",
"PinCode": 641105,
"State": "Tamil Nadu",
"Telephone2": "",
"Telephone1": [
"8667079713"
],
"Address1": [
"A-198,\nTamil annai street,Gandhi nagar,madukarai\nCoimbatore 641105"
]
},
"ReferenceNo": "5160",
"ReturnedDate": null,
"DestRecieveDate": "2018-12-20T07:56:22.518000",
"OriginRecieveDate": "2018-12-18T23:00:58.874000",
"OutDestinationDate": "2018-12-19T00:54:18.663000",
"CODAmount": 0,
"EWBN": [],
"FirstAttemptDate": null,
"ReverseInTransit": false,
"Scans": [
{
"ScanDetail": {
"ScanDateTime": "2018-12-18T00:33:37.614000",
"ScanType": "UD",
"Scan": "Manifested",
"StatusDateTime": "2018-12-18T00:33:37.614000",
"ScannedLocation": "BLR_Kudulu_CP (Karnataka)",
"Instructions": "Consignment Manifested",
"StatusCode": "X-UCI"
}
},
{
"ScanDetail": {
"ScanDateTime": "2018-12-20T17:57:28.002000",
"ScanType": "DL",
"Scan": "Delivered",
"StatusDateTime": "2018-12-20T17:57:28.002000",
"ScannedLocation": "Cjb_Kovaipudur_Dc (Tamil Nadu)",
"Instructions": "Delivered to consignee",
"StatusCode": "EOD-38"
}
}
],
}
}
]
}
Please help me get Shipment from this JSON file.
The exact error I am getting is
ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'Shipment' of undefined
It depends on which http module you are using.
For "#angular/common/http",
this.http.get('https://yourapi.com').subscribe(data => {
this.trackingorder = data;
console.log(this.trackingorder.ShipmentData);
}
For '#ionic-native/http',
this.http.get('https://yourapi.com').subscribe(data => {
this.trackingorder = JSON.parse(data);
console.log(this.trackingorder.ShipmentData);
}
If your using angular http then replace this line of code in your project.
change this line to
this.trackingorder = data;
Below line
this.trackingorder = data.json();
Should solve your problem. All the best.
I found the following method working .
Inside your .ts file use
this.http.get("https://track.delhivery.com/api/packages/json/?token=c7ac81cde31a5ea69d38cb098cab16cf7f909062&waybill=2285210000022")
.subscribe((userData) => {
console.log("shipment data" +userData);
this.users.push(userData);
});
Inside the HTML file , use the following
<div *ngFor ="let Scan of users[0].ShipmentData[0].Shipment.Scans" class="item h5">
<div *ngIf="Scan.ScanDetail.Scan=='Manifested'">
<h5 style="font-size:12px;color:black;">• {{Scan.ScanDetail.ScannedLocation}}</h5>
</div>
I am trying to get the array data in a JSON response. The following is my JSON response and I need to get all data to my html tags in component.
{
data : {
"topLikedMedia" : [
{
"id": "1546567845943506613_3718981156",
"type": "image",
"user": {
"id": "3718981156",
"username": "agoramonitor",
"full_name": "AgoraMonitor",
"profile_picture": "https://scontent.cdninstagram.com/t51.2885-19/s150x150/18809269_476795959342067_7353566623065702400_n.jpg"
},
"tags": [
"instagramers",
"content",
"socialmedia",
"marketing",
"branding",
"instagram"
],
"location": null,
"comments": {
"count": 2
},
"formatted_comments_count": "2",
"created_time": "1498585275",
"formatted_time": "Tue, Jun 27, 2017 7:41 PM",
"diff_humans_time": "4 months ago",
"link": "https://www.instagram.com/p/BV2g0MGgPa1/",
"likes": {
"count": 154
},
"formatted_likes_count": "154",
"images": {
"thumbnail": {
"width": 150,
"height": 150,
"url": "https://scontent.cdninstagram.com/t51.2885-15/s150x150/e35/c244.0.591.591/19533988_862713503881059_8677706625265434624_n.jpg"
},
"low_resolution": {
"width": 320,
"height": 175,
"url": "https://scontent.cdninstagram.com/t51.2885-15/s320x320/e35/19533988_862713503881059_8677706625265434624_n.jpg"
},
"standard_resolution": {
"width": 640,
"height": 350,
"url": "https://scontent.cdninstagram.com/t51.2885-15/s640x640/sh0.08/e35/19533988_862713503881059_8677706625265434624_n.jpg"
}
},
"caption": "Whether you want to drive leads to your homepage or encourage customer engagement ",
"userHasLiked": false,
"filter": "Normal"
}
],
}
I have the temp of this output and I need to receive this response and distribute it on its own tags and i dont know how
First solution, the Angular way :
getTopLiked() {
this._dashboardService.getTopPosts()
.subscribe(res => {
// Get your data in your component's variable
this.data = res.json();
});
}
In your HTML
<div *ngIf="data">
<div *ngFor="let liked of data.topLikedMedia">
<p>ID : {{liked.id}}</p>
<!-- And you do every other field like that -->
</div>
</div>
Second solution, the old Javascript way
getTopLiked() {
this._dashboardService.getTopPosts()
.subscribe(res => {
this.createMarkup(res.json());
});
}
createMarkup(data: Object) {
this.markup = '';
for (let liked of data.topLikedMedia) {
this.markup += `<p>ID : ${liked.id}</p>`;
// add the other fields like that
}
}
In your HTML
<div *ngIf="markup">
<div [innerHTML]="markup"></div>
</div>
I have a JSON file with the following format:
const data = [
{
"quantity": "200",
"prodType": "stock",
"symbol": "LOL",
"prodDesc": "Εθνική τράπεζα",
"market": "Greece",
"averageCost": "131,16",
"totalCost": "123,47",
"lastPrice": "121,123",
"value": "123,34",
"positionPercentage": "10",
"valueEUR": "113,23",
"pl": "1300",
"plPercentage": "12",
"plEuro": "1238",
"results": "12-01-2017",
"dividend": "12-03-2017",
"isin": "1234566"
}
]
I want to filter the data using their Product Type.
As a result, im creating an action
export function fetchSearchData(product_type) {
const filtered_data = data.filter(record=>
{
return record.prodType.match(product_type)
});
return {
type: FETCH_SEARCH_DATA,
payload: filtered_data
};
}
But it does not seem to work. Do you have any idea why?