Javier Bono
Javier Bono

Reputation: 9

Get method to Object in Object Angular 2

I have Data Model project in Angular 2. I have only three classes.

class Menu {
  name: string;
  categories: { [name: string]: Category };
}

class Category {
  name: string;
  dishes: { [name: string]: Dish };
}

class Dish {
  name: string;
}

In every class I have two methods created.

getName(){ return this.name } // in all classes

and

getCategory() { return this.categories } // in case of Menu class

getDishes() { return this.dishes } // in case of Category class

In my home.ts Component, I have the Data request (http request) from the backend, and I put all the data in those classes. This is working OK.

  getMenus() {
    this.globals.getMenus().subscribe(
      data => {
        this.menus = {};
        Object.keys(data).forEach(name => {
          this.menus[name] = new Menu(data[name]);
        });

        console.log(this.menus);
      },
      err => { console.log(err) }
    );
  }

console.log(this.menus) is working OK and prints all the data model correctly.

Now, my question is:

How can I use the get methods to make a list in my home.html with all the data, like:

  • Menu 1
  • "name of menu"
  • Category 1
  • "name of category"

    • Dish 1
      • "name of dish 1"
  • Category 2
  • "name of category 2"

    • Dish 1
      • "name of dish 1"
  • Menu 2

  • "name of menu 2
    • Category 1
    • ... etc

That's the Json Server Response:

{
  "menu_1": {
    "name": "Menú de día",
    "cat_1": {
      "name": "Entrantes",
      "dish_1": {
        "Name": "Ensalada Romana"
      },
      "dish_2": {
        "Name": "Sopa de galets"
      }
    },
    "cat_2": {
      "name": "Segundos",
      "dish_1": {
        "Name": "Calamares a la romana"
      },
      "dish_2": {
        "Name": "Tortilla de patatas"
      }
    }
  },
  "menu_2": {
    "name": "Menú Principal",
    "cat_1": {
      "name": "Primer Plato",
      "dish_1": {
        "Name": "Ensalada Romana"
      },
      "dish_2": {
        "Name": "Sopa de galets"
      }
    },
    "cat_2": {
      "name": "Segundo Plato",
      "dish_1": {
        "Name": "Calamares a la romana"
      },
      "dish_2": {
        "Name": "Tortilla de patatas"
      }
    },
    "cat_3": {
      "name": "Postres",
      "dish_1": {
        "Name": "Crema Catalana"
      }
    }
  }
}

Thanks in advance.

Upvotes: 0

Views: 5690

Answers (2)

slaesh
slaesh

Reputation: 16917

Angular's *ngFor will only work with iterable objects, not with maps.

Could look like this, using a Pipe to convert your maps into arrays:

<ul>
    <li *ngFor="let m of menus | mapToArray">
        {{ m.name }}
        <ul>
            <li *ngFor="let c of m.categories | mapToArray">
                {{ c.name }}
                <ul>
                    <li *ngFor="let d of c.dishes | mapToArray">
                        {{ d.name }}
                    </li>
                </ul>
            </li>
        </ul>
    </li>
</ul>

And the Pipe:

@Pipe({
  name: 'mapToArray'
})
export class MapToArrayPipe {
  public transform(map: any): any[] {
    if (!map) return [];
    return Object.keys(map).map(k => map[k]);
  }
}

live demo: https://plnkr.co/edit/HzwRftZXWnDlCZWJwL0d?p=preview

Upvotes: 0

Ankesh
Ankesh

Reputation: 4885

You can use Array in you class, to make it more statically typed.

class Menu {
  name: string;
  categories: Array<Category>; // initialize it as applicable
}
class Category {
  name: string;
  dishes: Array<Dish>;// initialize it as applicable
}
class Dish {
  name: string;
}

Component

You can try fill this.menus which will also be strongly typed Array<Menu> // make sure the code is writen to compile.

getMenus() {
    this.globals.getMenus().subscribe(
      data => {
        this.menus = new Array<Menu>();
        Object.keys(data).forEach(name => {
          //Initialize and push items as per data structure. 
          this.menus.push(new Menu(data[name]));
        });

        console.log(this.menus);
      },
      err => { console.log(err) }
    );
  }

template Arrange the following as a combination of Un-ordered and ordered list.

<ul>
    <li *ngFor="let menu of menus">
        {{ menu.name }}
        <ul>
            <li *ngFor="let category of menu.categories">
                {{ category.name }}
                <ul>
                    <li *ngFor="let dish of category.dishes">
                        {{ dish.name }}
                    </li>
                </ul>
            </li>
        </ul>
    </li>
</ul>

Upvotes: 1

Related Questions