15

i have a problem with my ionic 2/angular 2 app.

I got an app.ts where the hole "auth" part is implementet.

The code looks like this:

 import {Nav, Platform, Modal, ionicBootstrap} from "ionic-angular";
import {NavController} from "ionic-angular/index";
import {StatusBar} from "ionic-native";
import {Component, ViewChild} from "@angular/core";
import {AngularFire, FirebaseListObservable, FIREBASE_PROVIDERS, defaultFirebase} from "angularfire2";
import {HomePage} from "./pages/home/home";
import {AuthPage} from "./pages/auth/home/home";

@Component({
  templateUrl: "build/app.html",
})

class MyApp {
  @ViewChild(Nav) nav: Nav;

  authInfo: any;
  rootPage: any = HomePage;
  pages: Array<{title: string, component: any}>;

  constructor(private platform: Platform, private navCtrl: NavController, private af: AngularFire) {
    this.initializeApp();

    this.pages = [
      { title: "Home", component: HomePage }
    ];

  }

  initializeApp() {
    this.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();
    });
  }

  openPage(page) {
    this.nav.setRoot(page.component);
  }

  ngOnInit() {
    this.af.auth.subscribe(data => {
      if (data) {
        this.authInfo = data;
      } else {
        this.authInfo = null;
        this.showLoginModal();
      }
    });
  }

  logout() {
    if (this.authInfo) {
      this.af.auth.logout();
      return;
    }
  }

  showLoginModal() {
    let loginPage = Modal.create(AuthPage);
    this.navCtrl.present(loginPage);
  }
}

But now, when i try to run the app i get this message:

ORIGINAL EXCEPTION: No provider for NavController

Do you have any idea how to solve this problem? Thanks!

sebaferreras
  • 44,206
  • 11
  • 116
  • 134
Fargho
  • 1,267
  • 4
  • 15
  • 30

7 Answers7

20

You can not inject a NavController in a Root component via a constructor.

So, basically you can not do something like below:-

constructor(private nav: NavController){
}

This is how you can inject a NavController

@Controller({
  ....
})
class MyApp{
  @ViewChild('nav') nav: NavController;
  ....
  ....
  constructor(...){ // See, no NavController here
  }
  ....
}

And this is what Ionic docs has to say.

What if you want to control navigation from your root app component? You can't inject NavController because any components that are navigation controllers are children of the root component so they aren't available to be injected.

By adding a reference variable to the ion-nav, you can use @ViewChild to get an instance of the Nav component, which is a navigation controller (it extends NavController)

Community
  • 1
  • 1
Mav55
  • 4,080
  • 2
  • 21
  • 20
15

You can't inject the NavController in your Root Component so you should remove it from that part of the code. Further information can be found here.

Please make sure you already have a reference variable in your ion-nav, like this (the #myNav):

<ion-nav #myNav [root]="rootPage"></ion-nav>

And then you can get that reference by using ViewChild. You can then just navigate to another page, by using that property:

import { Nav, Platform, ... } from "ionic-angular";
// more imports...
// ...

@Component({
  templateUrl: "build/app.html"
})

class MyApp {
  @ViewChild('myNav') nav: NavController // <--- Reference to the Nav

  authInfo: any;
  rootPage: any = HomePage;
  pages: Array<{title: string, component: any}>;

  // Remove the "navCtrl: NavController" from the constructor, since
  // now your getting the reference from the view
  constructor(private platform: Platform, private af: AngularFire) {
    this.initializeApp();

    this.pages = [
      { title: "Home", component: HomePage }
    ];

  }

  // ...

  openPage(page) {
    // this.navCtrl.setRoot(page.component); <-- Wrong!
    this.nav.setRoot(page.component) // <-- Right! Use the this.nav property
  }

  // ...
}
sebaferreras
  • 44,206
  • 11
  • 116
  • 134
8

It's recommended you use this.app.getActiveNavs() in Ionic 3+ as getActiveNav() will be removed in the next major release, so your function can be written as:

showLoginModal() {
    let loginPage = Modal.create(AuthPage);
    this.getActiveNavs().slice(-1)[0].present(loginPage);
}

To push on the nav stack, you can just import the page (say YourPage) then:

this.getActiveNavs()[0].push(YourPage);

Old behaviour, for Ionic 2, deprecated in Ionic 3:

You can use this.getActiveNav() in Ionic 2 (and Ionic 3), so your function can be written as:

showLoginModal() {
    let loginPage = Modal.create(AuthPage);
    this.getActiveNav().present(loginPage);
}

With either method you don't need any import or private variable for this to work. If you're in a Component, just refer to your App:

import {App} from 'ionic-angular';
import {MyPage} from '../pages/my/page';

@Component()
export class MyComponent {
    constructor(private app: App) {
    }
    goToMyPage() {
        this.app.getActiveNav().push(MyPage);
    }
}
Yvan
  • 2,539
  • 26
  • 28
  • While this code snippet may be the solution, [including an explanation](//meta.stackexchange.com/questions/114762/explaining-entirely-‌​code-based-answers) really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. – Adam Apr 12 '17 at 15:08
  • Thanks @Adam, I've double post on two questions, so you're right, not really helpful here! I'm editing it right now. – Yvan Apr 13 '17 at 16:17
2

Ok, i just used the nav instead of NavigationController and now it works.

Fargho
  • 1,267
  • 4
  • 15
  • 30
2

I handled it with:

import { App, NavController } from 'ionic-angular';

constructor(protected app: App) {
... }

get navCtrl(): NavController {
    return this.app.getRootNav();
}

Answer taken from here: github issues

V. Aliosha
  • 152
  • 1
  • 1
  • 14
1

You named your nav incorrectly;

this.nav.setRoot(page.component);

Should be

this.navCtrl.setRoot(page.component);

And double check if your importing correctly

import { NavController} from 'ionic-angular';
LeRoy
  • 4,189
  • 2
  • 35
  • 46
  • This is not an error! `NavController` is correctly imported. The problem is that it cannot be injected here. He made a reference to `nav` by writing `@ViewChild(Nav) nav: Nav;`. `Nav` extends `NavController` so it can be used instead. – C.Champagne Nov 04 '16 at 22:50
0

One cause for this error is when you try to inject NavController into a provider class.
Like this:

@Injectable()
export class MyProviderService {

  constructor(private nav: NavController){
  }
}

I just had that error...
After removing this injection (and refactoring the code), it worked fine.

RicardoS
  • 2,088
  • 1
  • 21
  • 22