0

so I'm practicing some Angular/Ionic and am having a bit of a hard time figuring out why my *ngFor does not display my data. It seems simple enough for me, but I guess I'm doing something terribly wrong.

So I have an item.interface.ts that looks like this:

export interface Item {
    id: string;
    name: string;
}

an items.ts that looks like this:

export default [
  {
        items:[

        {
            id:'1',
            name:'Milk'
        },

        {
            id:'2',
            name:'Wheat'
        },

        {
            id:'3',
            name:'Cheese'
        }


              ]

    }

];

Then I have my home.ts:

    import { Component, OnInit } from '@angular/core';
    import { NavController, NavParams } from 'ionic-angular';

    import { Item } from '../../data/item.interface';
    import items from '../../data/items';



    @Component({
      selector: 'page-home',
      templateUrl: 'home.html'
    })

    export class HomePage implements OnInit {

        itemCollection: {items: Item[]}[];

      constructor(public navCtrl: NavController,
                  private navParams: NavParams){}

      ngOnInit(){
        this.itemCollection = items;
      }

  }

And finally my home.html:

<ion-header>
  <ion-navbar>
    <ion-buttons start>
        <button ion-button menuToggle>
            <ion-icon name="menu"></ion-icon>
        </button>
    </ion-buttons>
    <ion-title>Add Items</ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
    <ion-row>
        <ion-col text-center>
            <form>
                <label for="item">Type an item/ingredient name</label>
                <input type="text" name="item"><br>
                <button ion-button small type="submit">Add Item</button>
                <button ion-button small color="danger">Empty List</button>
            </form>
        </ion-col>
    </ion-row>  
    <ion-row>
        <ion-col>
            <ion-list>
                <button ion-item *ngFor="let singleItem of itemCollection">
                    <p>{{singleItem.name}}</p>
                </button>
            </ion-list>
        </ion-col>  
    </ion-row>
    <ion-row>
        <ion-col text-center>
            <button ion-button medium block>Scan</button>
        </ion-col>  
    </ion-row>    
</ion-content>

So when I do that ngFor in my home.html, it simply prints nothing, instead of the singleItem.name

Just as a curiosity, if I try to print singleItem.items.length, it does return 3, which looks correct, but for some reason it won't return the values from my data. Could you anyone help me with this, please? Cheers guys!

4
  • Do you get three buttons but no text or nothing at all? If you get three empty buttons then the problem is in reading the name. Otherwise the code thinks your item collection is empty. Commented Dec 30, 2017 at 23:57
  • Hey Steve, I get one empty button (!), I think you're right, it does think my itemCollection is empty, but can you spot why in my code? Commented Dec 31, 2017 at 0:03
  • console.log the collection after you set it in the init method. To get one button with no text your collection must be an array with a null in it, or maybe only one value from the items class but that seems unlikely. Commented Dec 31, 2017 at 0:07
  • By console.log my itemCollection, it did get the 3 items, but the issues was with the nesting objects, as Z.Bagley answered below. Thank you very much for your help Steve! Commented Dec 31, 2017 at 0:28

1 Answer 1

1

You're mixing up your levels, and you could make changes in different directions depending on your preference, but the general idea is your object and array of objects are getting nested in a way you're not expecting. Your *ngFor should look like this: *ngFor="let singleItem of itemCollection.items".

This is because itemCollections is defined as a object, with a single key-value pair. The key is items and items is defined to be the array of items you're looking to use in your *ngFor.

Sign up to request clarification or add additional context in comments.

5 Comments

Hey Z.Bagley, thank you very much, it made a lot of sense and tried it out, at first your suggestion didn't work, but I had to do it like this: *ngFor="let singleItem of itemCollection[0].items"
Hey Z.Bagley, I was just wondering, despite your solution is correct, I still would like to iterate through the array like my first try (*ngFor="let singleItem of itemCollection") do you have any suggestions on how to structure my code so it doesn't get nested the way it did? Cheers!
@DisplayName Swap itemCollection: {items: Item[]}[]; to itemCollection: Item[]; and this.itemCollection = items; to this.itemCollection = items[0].items; OR redefine your item.ts to just export a single items: [{id:'1',name:'Milk'},{id:'2',name:'Wheat'},{id:'3',name:'Cheese'}].
hmm I was able to do your first suggestion, but the second one (to redefine my items.ts) I'm getting: Type '{ items: { id: string; name: string; }[]; }' is not assignable to type 'Item[]'. Object literal may only specify known properties, and 'items' does not exist in type 'Item[]'.
export const items: [{ ... }] is what your file should look like. Don't wrap it all as an object in brackets {...}, which is where that error comes from. If it's wrapped in brackets {...} it's an object and is referred to by .keyName, so you'd have to still target items.items as you have it now.

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.