I’ve try to handle the navigation by the check of current authentication of user. I’ve use a Observable in my AuthProvider to check user authentication status and
I’ve use this to set the root page in my app.component.ts.
export class MyApp {
rootPage: any = LoginPage;
isLoggedIn$: Observable<boolean>;
enter code here
constructor(platform: Platform,
statusBar: StatusBar,
splashScreen: SplashScreen,
private authService: AuthServiceProvider) {
this.isLoggedIn$ = authService.isLoggedIn();
platform.ready().then(() => {
//check user logged
this.isLoggedIn$.subscribe(res => {
if (res) {
this.rootPage = TabsPage; //Home page if user is logged in
} else {
this.rootPage = LoginPage; //Login page if user isn't logged id
}
});
statusBar.styleDefault();
splashScreen.hide();
});
}
The check function isLoggedIn() in my authProvider is
ERROR TypeError: Cannot read property 'push' of null
at Tab.NavControllerBase._queueTrns (VM5768 vendor.js:51240)
at Tab.NavControllerBase.push (VM5768 vendor.js:51128)
at SafeSubscriber._next (VM5769 main.js:214)
at SafeSubscriber.__tryOrUnsub (VM5768 vendor.js:22842)
at SafeSubscriber.next (VM5768 vendor.js:22789)
at Subscriber._next (VM5768 vendor.js:22729)
at Subscriber.next (VM5768 vendor.js:22693)
at MapSubscriber._next (VM5768 vendor.js:124303)
at MapSubscriber.Subscriber.next (VM5768 vendor.js:22693)
at SwitchMapSubscriber.notifyNext (VM5768 vendor.js:135509)
First things first, You have to remove initialization statement from rootPage: any = LoginPage to rootPage: string;.
As you’ve mentioned that you’re using firebase, how about using onAuthStateChanged method to set the observer on the Auth object. Here’s my example code below.
It’s always a good idea to read the documentation.
export class MyApp {
rootPage: string;
constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen) {
const unsubscribe = firebase.auth().onAuthStateChanged(user => {
if (user) {
this.rootPage = 'TabsPage';
unsubscribe();
} else {
this.rootPage = 'LoginPage';
unsubscribe();
}
});
platform.ready().then(() => {
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
statusBar.styleDefault();
splashScreen.hide();
});
}
}
import { Component } from '@angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';
import { Observable } from 'rxjs/Observable';
import { TabsPage } from '../pages/tabs/tabs';
import { LoginPage } from '../pages/login/login';
import { AuthServiceProvider } from '../providers/auth-service/auth-service';
import { AngularFireAuth } from 'angularfire2/auth';
@Component({
templateUrl: 'app.html'
})
export class MyApp {
rootPage: string;
isLoggedIn$: Observable<boolean>;
constructor(platform: Platform,
statusBar: StatusBar,
splashScreen: SplashScreen,
private authService: AuthServiceProvider,
private afAuth: AngularFireAuth) {
const unsubscribe = afAuth.auth.onAuthStateChanged(user => {
if (user) {
this.rootPage = 'TabsPage';
unsubscribe();
} else {
this.rootPage = 'LoginPage';
unsubscribe();
}
});
platform.ready().then(() => {
statusBar.styleDefault();
splashScreen.hide();
});
}
}
but now, I have this error:
vendor.js:1703 ERROR Error: Uncaught (in promise): invalid link: TabsPage
at c (polyfills.js:3)
at Object.reject (polyfills.js:3)
at NavControllerBase._fireError (vendor.js:51282)
at NavControllerBase._failed (vendor.js:51275)
at vendor.js:51322
at t.invoke (polyfills.js:3)
at Object.onInvoke (vendor.js:4982)
at t.invoke (polyfills.js:3)
at r.run (polyfills.js:3)
at polyfills.js:3
It’s an invalid link because it’s (i’m assuming) not lazy-loaded. Only reference pages by putting strings around them if they are lazy-loaded ( have their own module.ts ) So you may have to remove the string from LoginPage as well. From what i see in your post, you’ve noticed different behavior based on whether or not a page is referenced with strings, and that is why.
lazy-loaded: reference with strings, and you don’t have to import into the component your referencing it in.
this.navController.push('ChildPage');
not lazy-loaded: import it into the component you’re referencing it in, and do not put strings around it.
@jaydz explained it very well.
Depending on the size of your application and some other factors you should consider the style of lazy loading that you want to use.
If you have a substantial amount of components then the best way would be a singular module. If you only have a few and you want to keep things simple by only importing the components module then a shared module.