Reputation: 9
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
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
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