How to conditionally set root page in Ionic 4

Hello,

Using Ionic 4, I want to set root page based on some condition while first app initialization.

i.e If app language is not set then root page should be SettingsPage and if language is already set then root page should be HomePage.

In Ionic 4 , there is no concept of setRootPage how can I set rootpage based on condition ?

Can anyone please help me how can I implement the same?

3 Likes

@dvtopiya Did you resolve it?

I just want the same thing. But condition should be only logged user anyway.

I think, it should help to set Root page on Application initialization, based on any condition

import {  Platform, NavController } from 'ionic-angular';
import { Router } from '@angular/router';

export class MyApp {

constructor(private platform: Platform, private router: Router) {
    platform.ready().then(() => {
      
    if(someCondition) { // if not login
      this.router.navigateByUrl('/');
   /*
   this will also work
   this.navCtrl.goRoot('/');
  */
    } else { // if login
     this.router.navigateByUrl('/app');
   /* this will also work
    this.navCtrl.goRoot('/app');
   */
    }
      
    });
  }
}
2 Likes

I am using this in ionic 3. But in ionic 4 is used Angular router. It means that my app-router.module.ts looks like:

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [
   {
       path: '',
       loadChildren: './login/login.module#LoginPageModule'
   },
   {
       path: 'app',
       loadChildren: './tabs/tabs.module#TabsPageModule'
   }
];

@NgModule({
   imports: [RouterModule.forRoot(routes)],
   exports: [RouterModule]
})
export class AppRoutingModule { } { }

So as root page is set Login page. But how to change it to app if user is logged?

For ionic3. On top of what hupptechnologies mentioned If you are using the tabs template provided by ionic. Then do it this way:

this.navCtrl.setRoot(Page1Page) // no quotes.

Assuming that Page1Page is the class name of the page you want.

For Ionic 3 I know it and I am using it, but as title says, we need it for ionic 4. Thanks

2 Likes

I have managed to get this working by having an authentication check in the component.ts


@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html'
})
export class AppComponent {

  showModal: boolean = false;
  modalContent: any;


  constructor(
    private platform: Platform,
    private splashScreen: SplashScreen,
    private statusBar: StatusBar,
    private userService: UserService,
    private router: Router,
    private modalService: ModalService,
    private renderer: Renderer2,
    @Inject(DOCUMENT) private _document
  ) {
    this.listenToAuth();
    this.initializeApp();
    this.listenToModal();
  }

  listenToAuth() {
       this.userService.afAuth.authState.subscribe(user => {
          if (user) {
        this.userService.getUserDataFromFirebase(user.uid)
          .subscribe((firebaseUser) => {
            if (firebaseUser) {
              this.userService.setUser(firebaseUser);
              // this.router.navigate(['tabs']);
              this.router.navigateByUrl('/tabs/(home:home)');
            } else {
              this.router.navigate(['']);
            }
          })
      } else {
        console.log('unauthenticated');
        this.router.navigate(['welcome']);
      }
    });
  }
1 Like

Hope it helps…

import {  Platform, NavController } from 'ionic-angular';
import { Router } from '@angular/router';

export class MyApp {

constructor(private platform: Platform, private router: Router) {
    platform.ready().then(() => {
      
    if(someCondition) { // if not login
      this.router.navigateByUrl('/');
   /*
   this will also work
   this.navCtrl.goRoot('/');
  */
    } else { // if login
     this.router.navigateByUrl('/app');
   /* this will also work
    this.navCtrl.goRoot('/app');
   */
    }
      
    });
  }
}
5 Likes

@hupptechnologies Thanks men, it works. I did not think it would be so easy :slight_smile:

1 Like

I have the same problem and tried doing what’s described here but I’m getting two issues:

  1. There is a slight delay, so I still first see the page that ‘’ redirects to in my app-routing.module.ts
  2. if the root page calls an asynchronous function, the redirect can occur while that is executing in which case the switch to a different page doesn’t happen cleanly, which breaks all sorts of things for me.

In the ionic 3 version of my app, I had this snippet in the app.html under the ion-menu:
<ion-nav [root]=“rootPage” main #content>
and then simply set this.rootPage in app.component.ts and that worked flawlessly. Any idea how I can achieve analogous behavious in ionic 4?

2 Likes

I would suggest the “guards” section of the Angular router docs.

2 Likes

Thanks, this helped, though there were some complications:
I started based on https://angularfirebase.com/lessons/ionic-4-routing-and-navigation-guide/#Guards
Now apparently, canActivate does not work on a path with a redirectTo, so I needed to apply that to the path that it redirected to and then keep track of whether this was the first load so that it didn’t completely prevent that path from being accessed. I did that via a property in a service that I included.

so in root.guard.ts:

canActivate(
  next: ActivatedRouteSnapshot,
  state: RouterStateSnapshot
): Observable<boolean> | Promise<boolean> | boolean {
  if (!this.globalsSrv.firstLoad) {
    return true;
  }
  this.globalsSrv.firstLoad = false;
  return Promise.all([/* retrieving some keys from storage here */]).then(values => {
    if (/* I want to redirect to a different page */) {
      this.router.navigateByUrl(/* alternative root page */);
      return false;
    } else {
      return true;
    }
  });
}

Hi,
I just come back to the app with version of ionic 4 and I am stuck on the same thing. I have condition like you wrote, but app is not redirected to home if condition is successful.

     if (localStorage.getItem('logged') === 'true') {
                console.log('LOGGED');
                this.router.navigateByUrl('/home');

            } else {
                console.log('NOT LOGGED')
                this.router.navigateByUrl('');
            }

I started the app with “tabs starter” and for now I have this error:
Error: Cannot match any routes. URL Segment: 'tabs/tab1'

My routs looks like:

const routes: Routes = [
  { path: '', loadChildren: './login/login.module#LoginPageModule' },
  { path: 'home', loadChildren: './tabs/tabs.module#TabsPageModule' },
];

Tabs routs:


const routes: Routes = [
  {
    path: 'tabs',
    component: TabsPage,
    children: [
      {
        path: 'tab1',
        children: [
          {
            path: '',
            loadChildren: '../tab1/tab1.module#Tab1PageModule'
          }
        ]
      },
      {
        path: 'tab2',
        children: [
          {
            path: '',
            loadChildren: '../tab2/tab2.module#Tab2PageModule'
          }
        ]
      },
      {
        path: 'tab3',
        children: [
          {
            path: '',
            loadChildren: '../tab3/tab3.module#Tab3PageModule'
          }
        ]
      },
      {
        path: '',
        redirectTo: '/tabs/tab1',
        pathMatch: 'full'
      }
    ]
  },
  {    path: '',
    redirectTo: '/tabs/tab1',
    pathMatch: 'full'
  }
];

Can you please help me to solve this?

Many thanks.

1 Like

Hi, did you find a solution?

just add app/ in tabs.router.module.ts like this.


Hi, I am currently having the delay issue, can you provide me with an example of your solution?

import Navcontroller like
import { Platform, ToastController, AlertController, MenuController, ModalController, NavController } from ‘@ionic/angular’;

Define In constructor
public navCtrl: NavController,

In Code use this way
this.navCtrl.navigateRoot(’/your-page-route-name’);

1 Like

There is a problem, if you are on home and clicking the back button on the hardware it returns to the login screen and this should not happen, unless you log out

3 Likes

Any solution to this issue?

I resolve this issue in this way
in src/app/app-routing.module.ts


import { NgModule } from ‘@angular/core’;
import { PreloadAllModules, RouterModule, Routes } from ‘@angular/router’;

const routes: Routes = [
{
path: ‘’,
** loadChildren: () => import(’./auth/login/login.module’).then(m => m.LoginPageModule)**
},
{
path: ‘tabs’,
loadChildren: () => import(’./tabs/tabs.module’).then(m => m.TabsPageModule)
},
];
@NgModule({
imports: [
RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })
],
exports: [RouterModule]
})
export class AppRoutingModule {}


in src/app/tabs/tabs-routing.module.ts


import { NgModule } from ‘@angular/core’;
import { RouterModule, Routes } from ‘@angular/router’;
import { TabsPage } from ‘./tabs.page’;

const routes: Routes = [
{
path: ‘tabs’,
component: TabsPage,
children: [
{
path: ‘tab1’,
children: [
{
path: ‘’,
loadChildren: () =>
import(’…/tab1/tab1.module’).then(m => m.Tab1PageModule)
}
]
},
{
path: ‘tab2’,
children: [
{
path: ‘’,
loadChildren: () =>
import(’…/tab2/tab2.module’).then(m => m.Tab2PageModule)
}
]
},
{
path: ‘tab3’,
children: [
{
path: ‘’,
loadChildren: () =>
import(’…/tab3/tab3.module’).then(m => m.Tab3PageModule)
}
]
},
{
path: ‘’,
** redirectTo: ‘tabs/tab1’,**
** pathMatch: ‘full’**
}
]
},
{
path: ‘’,
** redirectTo: ‘tabs/tab1’,**
** pathMatch: ‘full’**
}
];

@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class TabsPageRoutingModule {}


it works fine for me.