nested loop error when displaying in html after retrieve from API





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







1















I am new to ionic 3 and angular. Basically I wanted to create a list with header (data from MySQL database through PHP API). The header will display the category while the items will go to ion-item section.



However when I try to call the 2nd ngFor it throws me error as shown below in the picture. I notice a lot people use GET method while I am using POST method which are harder to find solution out there. Please enlighten, thanks in advance.



JSON



enter image description here



home.ts



this.storage.get('username').then((val) => {
let headers: any = new HttpHeaders({ 'Content-Type': 'application/x-www-form-urlencoded' }),
options: any = { "username": val },
url: any = "path_to_my_api";

this.http.post(url, options, headers)
.subscribe((data: any) => {
this.prods = data.products;
},
(error: any) => {
console.log(error);
});
});


home.html



<ion-list *ngFor="let prod of prods | async">
<ion-list-header>
{{prod.category}}
</ion-list-header>
<ion-item *ngFor="let myitem of prod.item | async">
<ion-avatar item-start>

</ion-avatar>
<h2>haha{{myitem.code}}</h2>
</ion-item>
</ion-list>









share|improve this question

























  • According to the error message, item is an object, not an array.

    – Ben Steward
    Nov 24 '18 at 17:37











  • how to make it become an array? But in console it is array, am I right? So weird

    – 4 Leave Cover
    Nov 24 '18 at 17:39











  • No, your second ngfor is entirely unnecessary. You’ve already begun to iterate over the array.

    – Ben Steward
    Nov 24 '18 at 17:40











  • I want all the items to be grouped in the category, if I only use 1 ngfor, the category will display as duplicate for every single item.

    – 4 Leave Cover
    Nov 24 '18 at 17:42











  • Ok, I see. I will update my answer in a minute.

    – Ben Steward
    Nov 24 '18 at 17:45


















1















I am new to ionic 3 and angular. Basically I wanted to create a list with header (data from MySQL database through PHP API). The header will display the category while the items will go to ion-item section.



However when I try to call the 2nd ngFor it throws me error as shown below in the picture. I notice a lot people use GET method while I am using POST method which are harder to find solution out there. Please enlighten, thanks in advance.



JSON



enter image description here



home.ts



this.storage.get('username').then((val) => {
let headers: any = new HttpHeaders({ 'Content-Type': 'application/x-www-form-urlencoded' }),
options: any = { "username": val },
url: any = "path_to_my_api";

this.http.post(url, options, headers)
.subscribe((data: any) => {
this.prods = data.products;
},
(error: any) => {
console.log(error);
});
});


home.html



<ion-list *ngFor="let prod of prods | async">
<ion-list-header>
{{prod.category}}
</ion-list-header>
<ion-item *ngFor="let myitem of prod.item | async">
<ion-avatar item-start>

</ion-avatar>
<h2>haha{{myitem.code}}</h2>
</ion-item>
</ion-list>









share|improve this question

























  • According to the error message, item is an object, not an array.

    – Ben Steward
    Nov 24 '18 at 17:37











  • how to make it become an array? But in console it is array, am I right? So weird

    – 4 Leave Cover
    Nov 24 '18 at 17:39











  • No, your second ngfor is entirely unnecessary. You’ve already begun to iterate over the array.

    – Ben Steward
    Nov 24 '18 at 17:40











  • I want all the items to be grouped in the category, if I only use 1 ngfor, the category will display as duplicate for every single item.

    – 4 Leave Cover
    Nov 24 '18 at 17:42











  • Ok, I see. I will update my answer in a minute.

    – Ben Steward
    Nov 24 '18 at 17:45














1












1








1








I am new to ionic 3 and angular. Basically I wanted to create a list with header (data from MySQL database through PHP API). The header will display the category while the items will go to ion-item section.



However when I try to call the 2nd ngFor it throws me error as shown below in the picture. I notice a lot people use GET method while I am using POST method which are harder to find solution out there. Please enlighten, thanks in advance.



JSON



enter image description here



home.ts



this.storage.get('username').then((val) => {
let headers: any = new HttpHeaders({ 'Content-Type': 'application/x-www-form-urlencoded' }),
options: any = { "username": val },
url: any = "path_to_my_api";

this.http.post(url, options, headers)
.subscribe((data: any) => {
this.prods = data.products;
},
(error: any) => {
console.log(error);
});
});


home.html



<ion-list *ngFor="let prod of prods | async">
<ion-list-header>
{{prod.category}}
</ion-list-header>
<ion-item *ngFor="let myitem of prod.item | async">
<ion-avatar item-start>

</ion-avatar>
<h2>haha{{myitem.code}}</h2>
</ion-item>
</ion-list>









share|improve this question
















I am new to ionic 3 and angular. Basically I wanted to create a list with header (data from MySQL database through PHP API). The header will display the category while the items will go to ion-item section.



However when I try to call the 2nd ngFor it throws me error as shown below in the picture. I notice a lot people use GET method while I am using POST method which are harder to find solution out there. Please enlighten, thanks in advance.



JSON



enter image description here



home.ts



this.storage.get('username').then((val) => {
let headers: any = new HttpHeaders({ 'Content-Type': 'application/x-www-form-urlencoded' }),
options: any = { "username": val },
url: any = "path_to_my_api";

this.http.post(url, options, headers)
.subscribe((data: any) => {
this.prods = data.products;
},
(error: any) => {
console.log(error);
});
});


home.html



<ion-list *ngFor="let prod of prods | async">
<ion-list-header>
{{prod.category}}
</ion-list-header>
<ion-item *ngFor="let myitem of prod.item | async">
<ion-avatar item-start>

</ion-avatar>
<h2>haha{{myitem.code}}</h2>
</ion-item>
</ion-list>






angular ionic-framework ionic3






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 24 '18 at 18:51









georgeawg

35k115470




35k115470










asked Nov 24 '18 at 17:13









4 Leave Cover4 Leave Cover

89992751




89992751













  • According to the error message, item is an object, not an array.

    – Ben Steward
    Nov 24 '18 at 17:37











  • how to make it become an array? But in console it is array, am I right? So weird

    – 4 Leave Cover
    Nov 24 '18 at 17:39











  • No, your second ngfor is entirely unnecessary. You’ve already begun to iterate over the array.

    – Ben Steward
    Nov 24 '18 at 17:40











  • I want all the items to be grouped in the category, if I only use 1 ngfor, the category will display as duplicate for every single item.

    – 4 Leave Cover
    Nov 24 '18 at 17:42











  • Ok, I see. I will update my answer in a minute.

    – Ben Steward
    Nov 24 '18 at 17:45



















  • According to the error message, item is an object, not an array.

    – Ben Steward
    Nov 24 '18 at 17:37











  • how to make it become an array? But in console it is array, am I right? So weird

    – 4 Leave Cover
    Nov 24 '18 at 17:39











  • No, your second ngfor is entirely unnecessary. You’ve already begun to iterate over the array.

    – Ben Steward
    Nov 24 '18 at 17:40











  • I want all the items to be grouped in the category, if I only use 1 ngfor, the category will display as duplicate for every single item.

    – 4 Leave Cover
    Nov 24 '18 at 17:42











  • Ok, I see. I will update my answer in a minute.

    – Ben Steward
    Nov 24 '18 at 17:45

















According to the error message, item is an object, not an array.

– Ben Steward
Nov 24 '18 at 17:37





According to the error message, item is an object, not an array.

– Ben Steward
Nov 24 '18 at 17:37













how to make it become an array? But in console it is array, am I right? So weird

– 4 Leave Cover
Nov 24 '18 at 17:39





how to make it become an array? But in console it is array, am I right? So weird

– 4 Leave Cover
Nov 24 '18 at 17:39













No, your second ngfor is entirely unnecessary. You’ve already begun to iterate over the array.

– Ben Steward
Nov 24 '18 at 17:40





No, your second ngfor is entirely unnecessary. You’ve already begun to iterate over the array.

– Ben Steward
Nov 24 '18 at 17:40













I want all the items to be grouped in the category, if I only use 1 ngfor, the category will display as duplicate for every single item.

– 4 Leave Cover
Nov 24 '18 at 17:42





I want all the items to be grouped in the category, if I only use 1 ngfor, the category will display as duplicate for every single item.

– 4 Leave Cover
Nov 24 '18 at 17:42













Ok, I see. I will update my answer in a minute.

– Ben Steward
Nov 24 '18 at 17:45





Ok, I see. I will update my answer in a minute.

– Ben Steward
Nov 24 '18 at 17:45












1 Answer
1






active

oldest

votes


















2














Try this



Logic:



this.http.post(url, options, headers)
.subscribe((data: any) => {
const categoryMap = data.products.reduce((categories, prod) => {
if (categories[prod.category]) {
categories[prod.category].push(prod);
} else {
categories[prod.category] = [prod];
}

return categories;
}, {});

this.categories = Object.keys(categoryMap).map(category => ({
category,
products: categoryMap[category]
});
}, (error: any) => {
console.log(error);
});


Template:



<ion-list *ngFor="let cat of categories | async">
<ion-list-header>
{{cat.category}}
</ion-list-header>
<ion-item *ngFor="let prod of cat.products | async"> <!-- not sure if async pipe is necessary here though -->
<ion-avatar item-start></ion-avatar>
<h2>haha{{prod.item.code}}</h2>
</ion-item>
</ion-list>


To clarify, the final structure of your data will look like this:



this.categories = [
{
category: "Beer Bottles",
products: [
{
item: {code: 'whatever'},
category: "Beer Bottles"
},
{
item: {code: 'something else'},
category: "Beer Bottles"
},
...etc.
]
},
{
category: "Beer Draught",
products: [ ...relevant products as above]
}
]





share|improve this answer





















  • 1





    appreciated your effort. Let me have a look and get back soon.

    – 4 Leave Cover
    Nov 24 '18 at 19:44











  • Many thanks to you as it is working as expected now! Can I know why do we need have two category, one in outer and another one in products array? Btw I removed the async.

    – 4 Leave Cover
    Nov 25 '18 at 7:49








  • 1





    In this particular implementation, it would have been more trouble to try and remove the category from the individual products than it was worth for a Stack Overflow answer. You could certainly try to remove it, but it is probably not necessary.

    – Ben Steward
    Nov 25 '18 at 13:04











  • Indeed, I will probably do it in the future when I have more understanding on this part. Thanks a lot anyway :)

    – 4 Leave Cover
    Nov 25 '18 at 16:43











  • Hi Ben, for example I added a search bar. Can I implement the filter feature with this logic? The search bar can search for multiple fields e.g. code, desc, uom etc. Can you show me how?

    – 4 Leave Cover
    Nov 30 '18 at 7:20














Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53460559%2fnested-loop-error-when-displaying-in-html-after-retrieve-from-api%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









2














Try this



Logic:



this.http.post(url, options, headers)
.subscribe((data: any) => {
const categoryMap = data.products.reduce((categories, prod) => {
if (categories[prod.category]) {
categories[prod.category].push(prod);
} else {
categories[prod.category] = [prod];
}

return categories;
}, {});

this.categories = Object.keys(categoryMap).map(category => ({
category,
products: categoryMap[category]
});
}, (error: any) => {
console.log(error);
});


Template:



<ion-list *ngFor="let cat of categories | async">
<ion-list-header>
{{cat.category}}
</ion-list-header>
<ion-item *ngFor="let prod of cat.products | async"> <!-- not sure if async pipe is necessary here though -->
<ion-avatar item-start></ion-avatar>
<h2>haha{{prod.item.code}}</h2>
</ion-item>
</ion-list>


To clarify, the final structure of your data will look like this:



this.categories = [
{
category: "Beer Bottles",
products: [
{
item: {code: 'whatever'},
category: "Beer Bottles"
},
{
item: {code: 'something else'},
category: "Beer Bottles"
},
...etc.
]
},
{
category: "Beer Draught",
products: [ ...relevant products as above]
}
]





share|improve this answer





















  • 1





    appreciated your effort. Let me have a look and get back soon.

    – 4 Leave Cover
    Nov 24 '18 at 19:44











  • Many thanks to you as it is working as expected now! Can I know why do we need have two category, one in outer and another one in products array? Btw I removed the async.

    – 4 Leave Cover
    Nov 25 '18 at 7:49








  • 1





    In this particular implementation, it would have been more trouble to try and remove the category from the individual products than it was worth for a Stack Overflow answer. You could certainly try to remove it, but it is probably not necessary.

    – Ben Steward
    Nov 25 '18 at 13:04











  • Indeed, I will probably do it in the future when I have more understanding on this part. Thanks a lot anyway :)

    – 4 Leave Cover
    Nov 25 '18 at 16:43











  • Hi Ben, for example I added a search bar. Can I implement the filter feature with this logic? The search bar can search for multiple fields e.g. code, desc, uom etc. Can you show me how?

    – 4 Leave Cover
    Nov 30 '18 at 7:20


















2














Try this



Logic:



this.http.post(url, options, headers)
.subscribe((data: any) => {
const categoryMap = data.products.reduce((categories, prod) => {
if (categories[prod.category]) {
categories[prod.category].push(prod);
} else {
categories[prod.category] = [prod];
}

return categories;
}, {});

this.categories = Object.keys(categoryMap).map(category => ({
category,
products: categoryMap[category]
});
}, (error: any) => {
console.log(error);
});


Template:



<ion-list *ngFor="let cat of categories | async">
<ion-list-header>
{{cat.category}}
</ion-list-header>
<ion-item *ngFor="let prod of cat.products | async"> <!-- not sure if async pipe is necessary here though -->
<ion-avatar item-start></ion-avatar>
<h2>haha{{prod.item.code}}</h2>
</ion-item>
</ion-list>


To clarify, the final structure of your data will look like this:



this.categories = [
{
category: "Beer Bottles",
products: [
{
item: {code: 'whatever'},
category: "Beer Bottles"
},
{
item: {code: 'something else'},
category: "Beer Bottles"
},
...etc.
]
},
{
category: "Beer Draught",
products: [ ...relevant products as above]
}
]





share|improve this answer





















  • 1





    appreciated your effort. Let me have a look and get back soon.

    – 4 Leave Cover
    Nov 24 '18 at 19:44











  • Many thanks to you as it is working as expected now! Can I know why do we need have two category, one in outer and another one in products array? Btw I removed the async.

    – 4 Leave Cover
    Nov 25 '18 at 7:49








  • 1





    In this particular implementation, it would have been more trouble to try and remove the category from the individual products than it was worth for a Stack Overflow answer. You could certainly try to remove it, but it is probably not necessary.

    – Ben Steward
    Nov 25 '18 at 13:04











  • Indeed, I will probably do it in the future when I have more understanding on this part. Thanks a lot anyway :)

    – 4 Leave Cover
    Nov 25 '18 at 16:43











  • Hi Ben, for example I added a search bar. Can I implement the filter feature with this logic? The search bar can search for multiple fields e.g. code, desc, uom etc. Can you show me how?

    – 4 Leave Cover
    Nov 30 '18 at 7:20
















2












2








2







Try this



Logic:



this.http.post(url, options, headers)
.subscribe((data: any) => {
const categoryMap = data.products.reduce((categories, prod) => {
if (categories[prod.category]) {
categories[prod.category].push(prod);
} else {
categories[prod.category] = [prod];
}

return categories;
}, {});

this.categories = Object.keys(categoryMap).map(category => ({
category,
products: categoryMap[category]
});
}, (error: any) => {
console.log(error);
});


Template:



<ion-list *ngFor="let cat of categories | async">
<ion-list-header>
{{cat.category}}
</ion-list-header>
<ion-item *ngFor="let prod of cat.products | async"> <!-- not sure if async pipe is necessary here though -->
<ion-avatar item-start></ion-avatar>
<h2>haha{{prod.item.code}}</h2>
</ion-item>
</ion-list>


To clarify, the final structure of your data will look like this:



this.categories = [
{
category: "Beer Bottles",
products: [
{
item: {code: 'whatever'},
category: "Beer Bottles"
},
{
item: {code: 'something else'},
category: "Beer Bottles"
},
...etc.
]
},
{
category: "Beer Draught",
products: [ ...relevant products as above]
}
]





share|improve this answer















Try this



Logic:



this.http.post(url, options, headers)
.subscribe((data: any) => {
const categoryMap = data.products.reduce((categories, prod) => {
if (categories[prod.category]) {
categories[prod.category].push(prod);
} else {
categories[prod.category] = [prod];
}

return categories;
}, {});

this.categories = Object.keys(categoryMap).map(category => ({
category,
products: categoryMap[category]
});
}, (error: any) => {
console.log(error);
});


Template:



<ion-list *ngFor="let cat of categories | async">
<ion-list-header>
{{cat.category}}
</ion-list-header>
<ion-item *ngFor="let prod of cat.products | async"> <!-- not sure if async pipe is necessary here though -->
<ion-avatar item-start></ion-avatar>
<h2>haha{{prod.item.code}}</h2>
</ion-item>
</ion-list>


To clarify, the final structure of your data will look like this:



this.categories = [
{
category: "Beer Bottles",
products: [
{
item: {code: 'whatever'},
category: "Beer Bottles"
},
{
item: {code: 'something else'},
category: "Beer Bottles"
},
...etc.
]
},
{
category: "Beer Draught",
products: [ ...relevant products as above]
}
]






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 24 '18 at 18:11

























answered Nov 24 '18 at 17:42









Ben StewardBen Steward

1,271616




1,271616








  • 1





    appreciated your effort. Let me have a look and get back soon.

    – 4 Leave Cover
    Nov 24 '18 at 19:44











  • Many thanks to you as it is working as expected now! Can I know why do we need have two category, one in outer and another one in products array? Btw I removed the async.

    – 4 Leave Cover
    Nov 25 '18 at 7:49








  • 1





    In this particular implementation, it would have been more trouble to try and remove the category from the individual products than it was worth for a Stack Overflow answer. You could certainly try to remove it, but it is probably not necessary.

    – Ben Steward
    Nov 25 '18 at 13:04











  • Indeed, I will probably do it in the future when I have more understanding on this part. Thanks a lot anyway :)

    – 4 Leave Cover
    Nov 25 '18 at 16:43











  • Hi Ben, for example I added a search bar. Can I implement the filter feature with this logic? The search bar can search for multiple fields e.g. code, desc, uom etc. Can you show me how?

    – 4 Leave Cover
    Nov 30 '18 at 7:20
















  • 1





    appreciated your effort. Let me have a look and get back soon.

    – 4 Leave Cover
    Nov 24 '18 at 19:44











  • Many thanks to you as it is working as expected now! Can I know why do we need have two category, one in outer and another one in products array? Btw I removed the async.

    – 4 Leave Cover
    Nov 25 '18 at 7:49








  • 1





    In this particular implementation, it would have been more trouble to try and remove the category from the individual products than it was worth for a Stack Overflow answer. You could certainly try to remove it, but it is probably not necessary.

    – Ben Steward
    Nov 25 '18 at 13:04











  • Indeed, I will probably do it in the future when I have more understanding on this part. Thanks a lot anyway :)

    – 4 Leave Cover
    Nov 25 '18 at 16:43











  • Hi Ben, for example I added a search bar. Can I implement the filter feature with this logic? The search bar can search for multiple fields e.g. code, desc, uom etc. Can you show me how?

    – 4 Leave Cover
    Nov 30 '18 at 7:20










1




1





appreciated your effort. Let me have a look and get back soon.

– 4 Leave Cover
Nov 24 '18 at 19:44





appreciated your effort. Let me have a look and get back soon.

– 4 Leave Cover
Nov 24 '18 at 19:44













Many thanks to you as it is working as expected now! Can I know why do we need have two category, one in outer and another one in products array? Btw I removed the async.

– 4 Leave Cover
Nov 25 '18 at 7:49







Many thanks to you as it is working as expected now! Can I know why do we need have two category, one in outer and another one in products array? Btw I removed the async.

– 4 Leave Cover
Nov 25 '18 at 7:49






1




1





In this particular implementation, it would have been more trouble to try and remove the category from the individual products than it was worth for a Stack Overflow answer. You could certainly try to remove it, but it is probably not necessary.

– Ben Steward
Nov 25 '18 at 13:04





In this particular implementation, it would have been more trouble to try and remove the category from the individual products than it was worth for a Stack Overflow answer. You could certainly try to remove it, but it is probably not necessary.

– Ben Steward
Nov 25 '18 at 13:04













Indeed, I will probably do it in the future when I have more understanding on this part. Thanks a lot anyway :)

– 4 Leave Cover
Nov 25 '18 at 16:43





Indeed, I will probably do it in the future when I have more understanding on this part. Thanks a lot anyway :)

– 4 Leave Cover
Nov 25 '18 at 16:43













Hi Ben, for example I added a search bar. Can I implement the filter feature with this logic? The search bar can search for multiple fields e.g. code, desc, uom etc. Can you show me how?

– 4 Leave Cover
Nov 30 '18 at 7:20







Hi Ben, for example I added a search bar. Can I implement the filter feature with this logic? The search bar can search for multiple fields e.g. code, desc, uom etc. Can you show me how?

– 4 Leave Cover
Nov 30 '18 at 7:20






















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53460559%2fnested-loop-error-when-displaying-in-html-after-retrieve-from-api%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







這個網誌中的熱門文章

Xamarin.form Move up view when keyboard appear

Post-Redirect-Get with Spring WebFlux and Thymeleaf

Anylogic : not able to use stopDelay()