Ionic 4 tabs navigation post login - Solution


#1

Hi ,

Seen so many post regarding navigation to tabs page from login page, here is an working example.

Create a ionic 4 project using - ionic start Sample tabs --type=angular.

Add a page called login - ionic g page login

And copy paste the below code page wise -

app-routing.module.ts

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 { }

tabs.page.html

<ion-tabs>
  <ion-tab label="Home" icon="ios-notifications" href="/app/tabs/(home:home)">
    <ion-router-outlet name="home"></ion-router-outlet>
  </ion-tab>
  <ion-tab label="About" icon="information-circle" href="/app/tabs/(about:about)">
    <ion-router-outlet name="about"></ion-router-outlet>
  </ion-tab>
  <ion-tab label="Contact" icon="contacts" href="/app/tabs/(contact:contact)">
    <ion-router-outlet name="contact"></ion-router-outlet>
  </ion-tab>
</ion-tabs>

Simply i have created a event on login page from where i simply navigating to tabs page -


**login.page.html**

<ion-header>
  <ion-toolbar>
    <ion-title>login</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content padding>
<ion-button (click)="navTabs()" expand="block">Navigate to tabs</ion-button>
</ion-content>

**login.page.ts**
async navTabs(){
    //you can use either of below
    this.route.navigateByUrl('/app/tabs/(home:home)');
    //this.navCtrl.navigateRoot('/app/tabs/(home:home)')
}

Screenshot -


Ionic 4 tabs page routing
Login page before tabs page - ionic 4
#2

Hi,

Just change navPage() to navTabs() and it works perfectly.

Thank’s a lot


#3

Hey, I did just like you said, however when I click the button I get an error “navTabs is not a function”.

I already had some pages/tabs set up, so insead of generating a new login page I used the already there home page.

Here is what I have now.

my app-routing.module.ts:

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

const routes: Routes = [
  {
    path: "",
    loadChildren: "./home/home.module#HomePageModule"
  },
  {
    path: "app",
    loadChildren: "./tabs/tabs.module#TabsPageModule"
  },
  {
    path: "dashboard",
    loadChildren: "./dashboard/dashboard.module#DashboardPageModule"
  },
  {
    path: "add-items",
    loadChildren: "./add-items/add-items.module#AddItemsPageModule"
  },
  {
    path: "deep",
    loadChildren: "./deep/deep.module#DeepPageModule"
  }
];
@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule {}

my home.page.html:

<ion-header color="primary">
  <ion-toolbar>
    <ion-title>Home</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content padding>
  <ion-button (click)="navTabs()" expand="block">Go to Dashboard</ion-button>
</ion-content>

and lastly my home.page.ts:

import { Component } from "@angular/core";
import { async } from "q";

async navTabs() {
  this.route.navigateByUrl("/app/tabs/dashboard:dashboard");
}

@Component({
  selector: "app-home",
  templateUrl: "home.page.html",
  styleUrls: ["home.page.scss"]
})
export class HomePage {}

note: when I use async (which, admittedly, i am not farmiliar with) I get an issue in vs code. it is looking for a ; that i don’t know where to put. I tried replacing async with function navTabs() which got rid of the issue, but still doesn’t work

when I serve the app it lands on the home page, but clicking on the button just gives this error:

ERROR TypeError: "_co.navTabs is not a function"
	View_HomePage_0 ng:///HomePageModule/HomePage.ngfactory.js:27:27
	handleEvent http://localhost:8100/vendor.js:41372:41
	callWithDebugContext http://localhost:8100/vendor.js:42465:22
	debugHandleEvent http://localhost:8100/vendor.js:42168:12
	dispatchEvent http://localhost:8100/vendor.js:38831:16
	renderEventHandlerClosure http://localhost:8100/vendor.js:39275:38
	decoratePreventDefault http://localhost:8100/vendor.js:57167:36
	invokeTask http://localhost:8100/polyfills.js:2743:17
	onInvokeTask http://localhost:8100/vendor.js:34932:24
	invokeTask http://localhost:8100/polyfills.js:2742:17
	runTask http://localhost:8100/polyfills.js:2510:28
	invokeTask http://localhost:8100/polyfills.js:2818:24
	invokeTask http://localhost:8100/polyfills.js:3862:9
	globalZoneAwareCallback http://localhost:8100/polyfills.js:3888:17
HomePage.html:8:2
ERROR CONTEXT 
Object { view: {…}, nodeIndex: 9, nodeDef: {…}, elDef: {…}, elView: {…} }
HomePage.html:8:2
View_HomePage_0
HomePage.html:8:2
proxyClass
compiler.js:10173
./node_modules/@angular/core/fesm5/core.js/DebugContext_.prototype.logError
core.js:11306
./node_modules/@angular/core/fesm5/core.js/ErrorHandler.prototype.handleError
core.js:1724
dispatchEvent
core.js:7714
renderEventHandlerClosure/<
core.js:8154:29
decoratePreventDefault/<
platform-browser.js:988
./node_modules/zone.js/dist/zone.js/</ZoneDelegate.prototype.invokeTask
zone.js:421
onInvokeTask
core.js:3811
./node_modules/zone.js/dist/zone.js/</ZoneDelegate.prototype.invokeTask
zone.js:420
./node_modules/zone.js/dist/zone.js/</Zone.prototype.runTask
zone.js:188
./node_modules/zone.js/dist/zone.js/</ZoneTask.invokeTask
zone.js:496
invokeTask
zone.js:1540
globalZoneAwareCallback

Not sure what i’m doing wrong :frowning: any help would be appreciated, thanks.


#4

I don’t know how your code got compiled it should not as you should put your function inside main class ( HomePage ) at least it did not compile for me, can you try below an let know-

Also put ionic info if below does not work.

home.page.ts

import { Component } from "@angular/core";

@Component({
  selector: "app-home",
  templateUrl: "home.page.html",
  styleUrls: ["home.page.scss"]
})
export class HomePage {
  async navTabs() {
    this.route.navigateByUrl("/app/tabs/dashboard:dashboard");
  }
}

#5

Nice, thanks for the prompt response!!

I moved the function to inside the main class, which got rid of all the issues i was having before, but I now get

{
	"resource": "/Users/nglhubbrich/projects/Sarcan/apps/earthSaverStats/src/app/home/home.page.ts",
	"owner": "typescript",
	"code": "2339",
	"severity": 8,
	"message": "Property 'route' does not exist on type 'HomePage'.",
	"source": "ts",
	"startLineNumber": 13,
	"startColumn": 10,
	"endLineNumber": 13,
	"endColumn": 15
}

I tried importing routes and routermodule thinking that was the issue, but it still has that error.

home.page.ts

import { Component } from "@angular/core";
import { async } from "q";
import { RouterModule, Routes } from "@angular/router";

@Component({
  selector: "app-home",
  templateUrl: "home.page.html",
  styleUrls: ["home.page.scss"]
})
export class HomePage {
  async navTabs() {
    this.route.navigateByUrl("/app/tabs/dashboard:dashboard");
  }
}

> ionic info
✔ Gathering environment info - done!

Ionic:

   ionic (Ionic CLI)             : 4.2.1 (/usr/local/lib/node_modules/ionic)
   Ionic Framework               : @ionic/angular 4.0.0-beta.13
   @angular-devkit/build-angular : 0.8.5
   @angular-devkit/schematics    : 0.8.5
   @angular/cli                  : 6.2.5
   @ionic/angular-toolkit        : 1.0.0

Cordova:

   cordova (Cordova CLI) : not installed
   Cordova Platforms     : not available
   Cordova Plugins       : not available

System:

   NodeJS : v8.11.2 (/usr/local/bin/node)
   npm    : 5.6.0
   OS     : macOS

#6

You are missing parentheses for the routes -

Wrong  -  this.route.navigateByUrl("/app/tabs/dashboard:dashboard");
Use Instead -  this.route.navigateByUrl("/app/tabs/(dashboard:dashboard)");

#7

Oh wow! that’s pretty silly of me haha!!

I also had to use this.router instead of this.route but it works all the same now!

Now I just have to figure out how to turn that button into and actual login authentication haha!!

Thank you so much for your help. I am (super) new to ionic and angular so I’m learning on the fly, you’ve been awesome! thank you!


#8

getting error
property ‘route’ does not exist on type ‘Loginpage’.

imported router module but not able to fix. please help.


#9

how you fix that ?
please share the solution.


#10

Paste your LoginPage html and ts here.


#11

Share your code to help you with your problem


#12

Found answer here: Navigation Changes

–>

const routes: Routes = [
{ path: 'login', loadChildren: './login/login.module#LoginPageModule' },
{ path: 'signup', loadChildren: './signup/signup.module#SignupPageModule' }
{ path: '', redirectTo: 'login', pathmatch:'full'},
{ path: '', loadChildren: './tabs/tabs.module#TabsPageModule' }, // <--- Important
]

the order is important too, you have to place it at the very bottom because it will match any path and the router selects the page with a first found algorithm


#13

Hi
i am getting this error when i click the button

ERROR Error: Uncaught (in promise): TypeError: Cannot read property ‘navigateByUrl’ of undefined
TypeError: Cannot read property ‘navigateByUrl’ of undefined
at LoginPage. (login.page.ts:12)

*** login.page.ts ***

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-login',
  templateUrl: './login.page.html',
  styleUrls: ['./login.page.scss'],
})
export class LoginPage implements OnInit {

  async navTabs(){
      //you can use either of below
      this.route.navigateByUrl('/app/tabs/(tab1:tab1)');
      //this.navCtrl.navigateRoot('/app/tabs/(tab1:tab1)')

  }

  constructor() { }

  ngOnInit() {}


}

*** app-routing.module.ts ***

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

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


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

*** login.page.html ***

<ion-header >
  <ion-toolbar color="primary">
    <ion-title style="color: #ffffff;">
      Sign in
    </ion-title>
  </ion-toolbar>
</ion-header>
<ion-content color="primary">
  <ion-card color="light">
    <ion-img src="/assets/cenr.jpg"></ion-img>
    <ion-card-header style="text-align: center">
        <ion-card-title style="color: #0074D9;">IOT BatMeter</ion-card-title>
    </ion-card-header>
    <ion-card-content>
      <ion-item>
        <ion-input required type="email" placeholder="Email"></ion-input>
      </ion-item>
      <ion-item>
        <ion-input required type="password" placeholder="Password"></ion-input>
      </ion-item>
      <div padding style="text-align: center">
        <ion-button (click)="navTabs()" shape="round" color="primary" fill="outline"><ion-icon name="key"></ion-icon> Sign in</ion-button>
      </div>
      <div style="text-align: center;padding: 3px;">
        <ion-button (click)="signOut()" size="small" shape="round" color="primary" fill="outline"><ion-icon name="create"></ion-icon> Sign up</ion-button>
      </div>
      <ion-button (click)="navTabs()" expand="block">Navigate to tabs</ion-button>
    </ion-card-content>
</ion-card>

</ion-content>

please help
best regards


#14

import router into login page and define it into constructor to use it, for more follow the instruction given in the example.


#15

Thank You so much! I’ve been trying since hours to get my navigation doing what I want it to do.
Did not get the idea of order-importance!
made my day!


#16

it works thanks a lot


#17

Such a relief … have been working on this for a long time


#18

Hey! Great tutorial bro, appreciate it. Although I have a slight problem in regards to login.page.ts . There seems to be a problem this.routes.navigateByUrl(’/app/tabs/(home:home)’); Keeps telling me that "Propery ‘route’ does not exist on type ‘LoginPage’. Help please. Kind of new here in ionic.

login.page.ts

import { Component, OnInit } from '@angular/core';
import { RouterModule, Routes, Router } from '@angular/router';
import { async } from "q";
@Component({
  selector: 'app-login',
  templateUrl: './login.page.html',
  styleUrls: ['./login.page.scss'],
})
export class LoginPage implements OnInit {

  constructor() { 
    
  }

  ngOnInit() {
  }

  async navTabs(){
    this.routes.navigateByUrl('/app/tabs/(home:home)');
  }
  

}

app-routing.module.ts

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

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

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

login.page.html

<ion-header>
  <ion-toolbar>
    <ion-title>login</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content padding>
<ion-button (click)="navTabs()" expand="block">Navigate to tabs</ion-button>
</ion-content>```

#19

@Kyushen - Declare the component into constructor, like below.

constructor(private routes: Router) { }

We always need to declare it first into constructor before using any components. :slight_smile:


#20

I have the same problem, always get this error. what caused the problem?Thank you all!

core.js:15714 ERROR Error: Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'app/tabs’
Error: Cannot match any routes. URL Segment: 'app/tabs’
at ApplyRedirects.push…/node_modules/@angular/router/fesm5/router.js.ApplyRedirects.noMatchError (router.js:2469)
at CatchSubscriber.selector (router.js:2450)
at CatchSubscriber.push…/node_modules/rxjs/_esm5/internal/operators/catchError.js.CatchSubscriber.error (catchError.js:34)
at MapSubscriber.push…/node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._error (Subscriber.js:80)
at MapSubscriber.push…/node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.error (Subscriber.js:60)
at MapSubscriber.push…/node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._error (Subscriber.js:80)
at MapSubscriber.push…/node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.error (Subscriber.js:60)
at MapSubscriber.push…/node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._error (Subscriber.js:80)
at MapSubscriber.push…/node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.error (Subscriber.js:60)
at TapSubscriber.push…/node_modules/rxjs/_esm5/internal/operators/tap.js.TapSubscriber._error (tap.js:61)
at resolvePromise (zone.js:831)
at resolvePromise (zone.js:788)
at zone.js:892
at ZoneDelegate.push…/node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
at Object.onInvokeTask (core.js:17280)
at ZoneDelegate.push…/node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:422)
at Zone.push…/node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:195)
at drainMicroTaskQueue (zone.js:601)
at ZoneTask.push…/node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask [as invoke] (zone.js:502)
at invokeTask (zone.js:1744)

and login.html is

<ion-header>
  <ion-toolbar>
    <ion-buttons slot="start">
      <ion-back-button></ion-back-button>
    </ion-buttons>
    <ion-title>Login</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content padding >
  <ion-card>
    <ion-item>
      <ion-label position="floating" >Account</ion-label>
      <ion-input  clearInput="true" required="true" type="email"  [(ngModel)]="userLogin.email"></ion-input>
    </ion-item>

    <ion-item>
      <ion-label position="floating">Password</ion-label>
      <ion-input  clearInput="true" required="true" type="password" minlength = 6  [(ngModel)]="userLogin.password"></ion-input>
    </ion-item>

    <ion-item>
      <ion-button class="loginButton" color="primary" expand="full" size="medium" shape="round" (click)="login()" >

        <ion-ripple-effect></ion-ripple-effect>
        <ion-icon slot="start" name="star"></ion-icon>
        login</ion-button>
    </ion-item>
    <ion-item >
      <ion-badge color="secondary" slot="start"  (click)="goAccountForRegister()"> <ion-icon slot="start" name="star"></ion-icon>new account</ion-badge>
      <ion-badge color="secondary" slot="end">forgot password</ion-badge>
    </ion-item>
  </ion-card>

</ion-content>

and login.module.ts is

import { Component, OnInit } from '@angular/core';
import {BasePage} from '../../base/base.page';
import {BaseInterceptor} from '../../http-interceptors/base-interceptor';
import {AuthService} from '../../services/auth.service';
import {ActivatedRoute, Router} from '@angular/router';
import {LoadingController, NavController, ToastController} from '@ionic/angular';
import {HttpClient} from '@angular/common/http';
import {applyRedirects} from '@angular/router/src/apply_redirects';

@Component({
  selector: 'app-login',
  templateUrl: './login.page.html',
  styleUrls: ['./login.page.scss'],
})
export class LoginPage extends BasePage implements OnInit {

  private userLogin = {email: 'hubaokun@gmail.com',  password : '123321'}

  constructor(public auth: AuthService,
              public router: Router,
              public nav: NavController,
              public loadingController: LoadingController,
              public toastController: ToastController,
              public http: HttpClient) {
      // @ts-ignore
      super(router,
          nav,
          loadingController,
          toastController,
          http);
  }

  ngOnInit() {
  }

    async login() {
    this.presentLoading();
    this.http.post('/api/iv1/user/login', this.userLogin).subscribe(
        (result) => {
          this.presentToast('login successfully!');
          console.log(result);
            // BaseInterceptor.auth = result;
            this.auth.saveAuth(result);
            // this.nav.navigateForward('/account'); // It can navigate to a single page, but not tabs
            this.router.navigateByUrl('/app/tabs/(tab1:tab1)');
            // this.router.navigate(['/tabs/tab1']);

          },
        err => {
          this.presentToast('login failed!');
        },
        () => {
          console.log('it`s over');
        }
    );
  }


  goAccountForRegister() {
    this.nav.navigateForward('/account');

  }

}

and the tabs.router.module.ts is

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: '../tab1/tab1.module#Tab1PageModule'
          }
        ]
      },
      {
        path: 'tab2',
        children: [
          {
            path: '',
            loadChildren: '../tab2/tab2.module#Tab2PageModule'
          }
        ]
      },
      {
        path: 'setting',
        children: [
          {
            path: '',
            loadChildren: '../setting/setting.module#SettingPageModule'
          }
        ]
      },
      {
        path: '',
        redirectTo: '/tabs/tab1',
        pathMatch: 'full'
      }
    ]
  },
  {
    path: '',
    redirectTo: '/tabs/setting',
    pathMatch: 'full'
  }
];

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

app-routing.module.ts is

import { NgModule } from '@angular/core';
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';
import {TabsPage} from './tabs/tabs.page';
const routes: Routes = [
  { path: 'base', loadChildren: './base/base.module#BasePageModule' },
  { path: 'setting', loadChildren: './setting/setting.module#SettingPageModule' },
  { path: 'login', loadChildren: './account/login/login.module#LoginPageModule' },
  { path: 'register/:account/:code', loadChildren: './account/register/register.module#RegisterPageModule' },
  { path: 'account', loadChildren: './account/account/account.module#AccountPageModule' },
  { path: 'forget-password', loadChildren: './account/forget-password/forget-password.module#ForgetPasswordPageModule' },
  { path: '',
    redirectTo: '/login',
    pathMatch: 'full'
  },

  { path: 'app', loadChildren: './tabs/tabs.module#TabsPageModule' }
];
@NgModule({
  imports: [
    RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule {

}

and the basePage is

import { Component, OnInit } from '@angular/core';
import {Router, ActivatedRoute} from '@angular/router';
import {LoadingController, NavController, ToastController} from '@ionic/angular';
import { HttpClient } from '@angular/common/http';
import {AuthService } from '../services/auth.service';

@Component({
  selector: 'app-base',
  templateUrl: './base.page.html',
  styleUrls: ['./base.page.scss'],
})
export class BasePage implements OnInit {


  constructor(public router: Router,
              public nav: NavController,
              public loadingController: LoadingController,
              public toastController: ToastController,
              public http: HttpClient) {
  }


  ngOnInit() {
  }

  async presentLoading() {
    const loading = await this.loadingController.create({
      message: 'Hellooo',
      duration: 2000
    });
    await loading.present();

    const { role, data } = await loading.onDidDismiss();

    console.log('Loading dismissed!');
  }

  async presentLoadingWithOptions() {
    const loading = await this.loadingController.create({
      spinner: null,
      duration: 5000,
      message: 'Please wait...',
      translucent: true,
      cssClass: 'custom-class custom-loading'
    });
    return await loading.present();
  }

  async presentToast(message: string) {
    const toast = await this.toastController.create({
      message: message,
      duration: 2000
    });
    toast.present();
  }

  async presentToastWithOptions(message: string) {
    const toast = await this.toastController.create({
      message: message,
      showCloseButton: true,
      position: 'top',
      closeButtonText: 'Done'
    });
    toast.present();
  }
}