Dynamic menu with dynamic page navigation


#1

I’m building an app where the data comes from the server. The menu is dynamic, and the server can send different menus depending on the user profile. I will never know what will be the component/page, that the menu item will have, I just need to have that component/page available.

The main problem is that I need to do a lot of components/pages imports and I do not want to that in every component/page.

I created a service, where all the imports are made and a method exists to return the correct component, so the navController could navigate.

import { Injectable } from '@angular/core';

//Import navigation pages
import { NotificationsPage } from "./../pages/notifications/notifications";
import { ClubPage } from "./../pages/club/club";
import { ActivitiesPage } from "./../pages/activities/activities";
import { NewsPage } from "./../pages/news/news";
import { CalendarPage } from "./../pages/calendar/calendar";
import { NewsletterPage } from "./../pages/newsletter/newsletter";
import { SettingsPage } from "./../pages/settings/settings";
import { FavoritesPage } from "./../pages/favorites/favorites";
import { SubmenuPage } from "./../pages/submenu/submenu";
import { ContentDetailsPage } from "./../pages/contentdetails/contentdetails";

@Injectable()
export class ViewNavigatorService
{
      public NOTIFICATIONS:string = "notifications";
      public CLUB:string = "club";
      public ACTIVITIES:string = "activities";
      public NEWS:string = "news";
      public CALENDAR:string = "calendar";
      public NEWSLETTER:string = "newsletter";
      public SETTINGS:string = "settings";
      public FAVORITS:string = "favorits";
      
      public SUBMENU:string = "submenu";
      public CONTENT_DETAILS:string = "content-details";

      public GetComponent(page:string, data?:any):any
      {
            let Component = null;
            
            switch (page) 
            {
                  case this.NOTIFICATIONS:      Component = NotificationsPage;     break;
                  case this.CLUB:               Component = ClubPage;              break;
                  case this.ACTIVITIES:         Component = ActivitiesPage;        break;
                  case this.NEWS:               Component = NewsPage;              break;
                  case this.CALENDAR:           Component = CalendarPage;          break;
                  case this.NEWSLETTER:         Component = NewsletterPage;        break;
                  case this.SETTINGS:           Component = SettingsPage;          break;
                  case this.FAVORITS:           Component = FavoritesPage;         break;
                  case this.SUBMENU:            Component = SubmenuPage;           break;
                  case this.CONTENT_DETAILS:    Component = ContentDetailsPage;    break;
            
                  default:                      Component = null;                  break;
            }

            return Component;
      }
}

If I only inject the service in a parent page it works, but if I also inject the service in a child page, I get this error:

Can’t resolve all parameters for SubmenuPage: (NavController, NavParams, PopoverController, AlertController, ModalController, ?).

The ? should be the “ViewNavigatorService”.

Why this error happens?

Is there a better way to do this? What are you using when your app uses dynamic navigation?


#2

If I understand correctly, you need to populate the side menu based on logged in user. I have done the same and you just need to add the components in side menu page. you don’t need to add components in every page.

below is my code in app.component.ts

i have below variable added all my components
this.pages = [
{title: ‘HomePage’, component:HomePage},
{title: ‘AlertsPage’, component: AlertsPage},
{title: ‘ContactusPage’, component:ContactusPage},
{title: ‘CustomersPage’, component:CustomersPage},
{title: ‘OrdersPage’, component:OrdersPage},
{title: ‘PaymentsPage’, component:PaymentsPage},
{title: ‘ProductLinesPage’, component:ProductLinesPage},
{title: ‘ProductsPage’, component:ProductsPage},
{title: ‘PromotionsPage’, component:PromotionsPage},
{title: ‘SettingsPage’, component:SettingsPage}
];

published an event in login service upon successful login
this.events.publish(‘userloggedin’);
subscribed same in app.component.ts constructor

 this.events.subscribe('userloggedin',(() => {console.log('event received');
this.getMenuOptions(); }));

and invoked service to get the menuoptions from service and populated the menu

below function is invoked from page
openPage(page) {
// Reset the content nav to have just this page
// we wouldn’t want the back button to show in this scenario

let i = this.getpagenav(page.descpt);
console.log(i);
 this.nav.setRoot(this.pages[i].component);

}

which inturn invoked below function
getpagenav = function(pagecomp:string):number{
for (let x=0;x<this.pages.length;x++){
if(pagecomp == this.pages[x].title){
return x;
}
}
return 0;
}

this above is working fine for me and please check the pages object. title is same as component name.

hope this helps. Please let me know, if any questions.

Thanks,
Raj