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>
5
  • According to the error message, item is an object, not an array. Commented Nov 24, 2018 at 17:37
  • how to make it become an array? But in console it is array, am I right? So weird Commented Nov 24, 2018 at 17:39
  • No, your second ngfor is entirely unnecessary. You’ve already begun to iterate over the array. Commented Nov 24, 2018 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. Commented Nov 24, 2018 at 17:42
  • Ok, I see. I will update my answer in a minute. Commented Nov 24, 2018 at 17:45

1 Answer 1

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]
  }
]
Sign up to request clarification or add additional context in comments.

6 Comments

appreciated your effort. Let me have a look and get back soon.
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.
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.
Indeed, I will probably do it in the future when I have more understanding on this part. Thanks a lot anyway :)
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?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.