Adding providers to app.js results in no provider for NavController error?


#1

So I saw that if you want to access some data globally in the App, you should do so through an @Injectable service that is declared in app.js and then you use it everywhere else, like so:

app.js:

    @App({
      template: '<ion-nav [root]="rootPage"></ion-nav>',
      providers: [[CropModel],[SyncModel],[AuthService]],
      config: {}
    })
    export class MyApp {
      static get parameters() {
        return [[Platform],[CropModel],[SyncModel],[AuthService]];
      }

    constructor(platform,crops,syncs,auth) {
    this.cropStorage = new CropModel();
    this.syncModel = new SyncModel();
    this.auth=auth;
    this.rootPage = NoSyncStart;
      
    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();
    });
    }
    }

And then on every other page I have, for example:

    @Page({
      templateUrl: 'build/pages/accountOptions/accountOptions.html'
    })
    export class AccountOptions {
    static get parameters() {
        return [[NavController],[AuthService]];
    }

    constructor(nav, auth) {
        this.auth = auth;
        this.nav = nav;
    }
    }

But this results in an error as soon as I load it up, where there’s no provider for NavController on app.js; there shouldn’t be, I’m aware, but then what’s up with the error?


#2

What version of ionic-angular are you using? If beta8, check the changelog for new bootstrap syntax.


#3

Currently on Beta 7.


#4

I believe that you have a mistake in the declaration of the providers - unlike with static get parameters() it should be a simple (one-dimensional) array, i.e. change it this way:

@App({
  template: '<ion-nav [root]="rootPage"></ion-nav>',
  providers: [CropModel, SyncModel, AuthService],
  config: {}
})

#5

Alright thanks, I changed that but still getting the same error.


#6

Check also your other files for similar errors - it seems that something is messing up the Angular 2 DI.


#7

No providers being declared anywhere else - that’s the way to have those three providers share data globally, correct?


#8

Ok, how about removing CropModel and SyncModel from the providers? From this code sample it looks like you’re using them only in app.js and you’re not even using them via DI. Update your code like this and see what happens then:

// ...
@App({
  template: '<ion-nav [root]="rootPage"></ion-nav>',
  providers: [AuthService],
  config: {}
})
export class MyApp {
    static get parameters() {
        return [[Platform], [AuthService]];
    }

    constructor(platform, auth) {
// ...

#9

It seems that if I list any providers in app.js, I get the NavController error; everything works fine if I then proceed to declare the providers in the pages they’re used in, but then they’re not global, correct?


#10

Even only with AuthService as a single provider there? Does it work if you move the AuthService from there to any page that uses it (yes, then a separate instance of the service is created for each page)? Aren’t there any other errors suggesting where the problem might be?


#11

Yes, if I have even a single provider listed on the @App, then it throws that NavController error; in the stacktrace it says DI Exception followed by several app.bundle.js lines.

If I move the services only to the pages where they’re used, then they work, for that page.


#12

So, I updated to beta 8 and see if maybe something worked differently; this is my app.js now:

    import {Component} from '@angular/core';
    import {ionicBootstrap, Platform} from 'ionic-angular';
    import {StatusBar} from 'ionic-native';
    import {NoSyncStart} from './pages/noSyncStart/noSyncStart';
    import {AuthService} from './services/authservice';

    @Component({
      template: '<ion-nav [root]="rootPage"></ion-nav>',
    })
    export class MyApp {
      static get parameters() {
        return [[Platform],[AuthService]];
      }

      constructor(platform,auth) {
        //this.cropStorage = new CropModel();
        //this.syncModel = new SyncModel();
        this.auth=auth;
        this.rootPage = NoSyncStart;
          
        platform.ready().then(() => {
          StatusBar.styleDefault();
        });
      }
    }
    ionicBootstrap(MyApp, [AuthService], {});

And the exact error I’m getting now is:

ORIGINAL EXCEPTION: No provider for NavController! (AuthService -> NavController)

Which seems to provide some more information; like it’s attempting to override NavController with the first provider I use?


#13

Could you post some of the code of the AuthService - from the imports up-to the constructor() (including the constructor() itself)?


#14
import {NavController} from 'ionic-angular';
import {Injectable, Inject} from '@angular/core';
import {Http, Headers} from '@angular/http';


@Injectable()
export class AuthService {
    static get parameters() {
        return [[Http],[NavController]];
    }

    constructor(http, navcontroller) {
        this.http = http;
        this.nav = navcontroller;
        this.isLoggedin = false;
        this.language = navigator.language.split('-')[0];
        if(window.localStorage.getItem('logToken')){
            this.isLoggedin = true;
        }
    }

#15

Attempting to access view-layer things (like NavController) from model-layer things (like services) is a symptom of broken design.


#16

Okay, yeah, I just realized what it was as I was posting that.

I’m…not entirely sure why was that in there.

I apologize for wasting everyone’s time.


#17

@arfons I completely agree with @rapropos comment above and I would recommend you to try to keep the service and presentation logic separated.


#18

I don’t even use NavController there, must’ve made a terrible copy paste somewhere.


#19

It happens, I’m glad that you figured it out and managed to solve the problem. :slight_smile: