I have been tearing my hair out with trying to parse and use data returned form a JSON query/ api call. Im not sure exactly where i was going wrong, i feel like i have been circling the answer for days, chasing various error codes like:
"Cannot find 'iterableDiff' pipe supporting object"
"Generic TYpe Array requires one argument(s)"
JSON parsing Errors, and im sure others
Im assuming i just had the wrong combination of fixes.
So here's a bit of a summary of gotchas and things to look for.
Firstly check the result of your api calls, your results may be in the form of an object, an array, or an array of objects.
i wont go into it too much, suffice to say the OP's original Error of not being iterable is generally caused by you trying to iterate an object, not an Array.
Heres some of my debugging results showing variables of both arrays and objects
So as we generally would like to iterate over our JSON result we need to ensure it is in the form of an Array. I tried numerous examples, and perhaps knowing what i know now some of those would in fact work, but the approach i went with was indeed to implement a pipe and the code i used was that the posted by t.888
transform(obj: {[key: string]: any}, arg: string) {
if (!obj)
return undefined;
return arg === 'keyval' ?
Object.keys(obj).map((key) => ({ 'key': key, 'value': obj[key] })) :
arg === 'key' ?
Object.keys(obj) :
arg === 'value' ?
Object.keys(obj).map(key => obj[key]) :
null;
Honestly i think one of the things that was getting me was the lack of error handling, by adding the 'return undefined' call i believe we are now allowing for non expected data to be sent to the pipe, which obviously was occurring in my case.
if you don't want to deal with argument to the pipe (and look i don't think it's necessary in most cases) you can just return the following
if (!obj)
return undefined;
return Object.keys(obj);
Some Notes on creating your pipe and page or component that uses that pipe
is i was receiving errors about ‘name_of_my_pipe’ not being found
Use the ‘ionic generate pipe’ command from the CLI to ensure the pipe modules.ts are created and referenced correctly. ensure you add the following to the mypage.module.ts page.
import { PipesModule } from ‘…/…/pipes/pipes.module’;
(not sure if this changes if you also have your own custom_module, you may also need to add it to the custommodule.module.ts)
if you used the 'ionic generate page' command to make your page, but decide to use that page as your main page, remember to remove the page reference from app.module.ts (here's another answer i posted dealing with that https://forum.ionicframework.com/t/solved-pipe-not-found-in-custom-component/95179/13?u=dreaser
In my searching for answers there where a number of ways to display the data in the html file, and i don't understand enough to explain the differences. You may find it better to use one over another in certain scenarios.
<ion-item *ngFor="let myPost of posts">
<img src="https://somwhereOnTheInternet/{{myPost.ImageUrl}}"/>
<img src="https://somwhereOnTheInternet/{{posts[myPost].ImageUrl}}"/>
<img [src]="'https://somwhereOnTheInternet/' + myPost.ImageUrl" />
</ion-item>
However what worked that allowed me to display both the value and the key was the following:
<ion-list>
<ion-item *ngFor="let myPost of posts | name_of_pip:'optional_Str_Varible'">
<h2>Key Value = {{posts[myPost]}}
<h2>Key Name = {{myPost}} </h2>
</ion-item>
</ion-list>
to make the API call it looks like you need to import HttpModule into app.module.ts
import { HttpModule } from '@angular/http';
.
.
imports: [
BrowserModule,
HttpModule,
and you need Http in the page you make the call from
import {Http} from '@angular/http';
When making the API call you seem to be able to get to the children data (the objects or arrays within the array) 2 different ways, either seem to work
either during the call
this.http.get('https://SomeWebsiteWithAPI').map(res => res.json().anyChildren.OrSubChildren).subscribe(
myData => {
or when you assign the data to your local variable
posts: Array<String>;
this.posts = myData['anyChildren'];
(not sure if that variable needs to be an Array String, but thats what i have it at now. It may work as a more generic variable)
And final note, it was not necessary to use the inbuilt JSON library
however you may find these 2 calls handy for converting from an object to a string and vica versa
var stringifiedData = JSON.stringify(this.movies);
console.log("**mResults in Stringify");
console.log(stringifiedData);
var mResults = JSON.parse(<string>stringifiedData);
console.log("**mResults in a JSON");
console.log(mResults);
I hope this compilation of info helps someone out.