Ionic 2 Importing Providers - Cannot find name

Hi,

I’m trying to import a provider but ionic 2 keeps saying

Cannot find name 'RateService'.

Below is everywhere I have imported it. For what I can see it should work, I believe I have done everything I need to, anyone got any ideas? Thanks.

app.module.ts

import { RateService } from '../providers/rate-service/rate-service';

providers: [{provide: ErrorHandler, useClass: IonicErrorHandler}, Storage, RateService]

information.ts

import { RateService } from '../../providers/rate-service/rate-service';

  constructor(public navCtrl: NavController, public viewCtrl: ViewController, public storage: Storage, public alertCtrl: AlertController, public rateService: RateService, public platform: Platform) 
  {}

Then call from a button press…

  review() {
    this.rateService.promptForRating();
  }

rate-service.ts

import { Injectable } from '@angular/core';
import { Platform } from 'ionic-angular';
import { AppRate } from 'ionic-native';

@Injectable()
export class RateService {
  
  appRate: any = AppRate;
  
  constructor(public platform: Platform) {
    
    this.platform.ready().then(
      () => {
        this.appRate.preferences.storeAppURL = {
          ios: '849930087',
          android: 'market://details?id=com.carlrydings.craftingguideforminecraft',
          windows: 'ms-windows-store://pdp/?ProductId=9nblggh1z0w3',
        };
        this.appRate.preferences.usesUntilPrompt = 2;
        this.appRate.preferences.customLocale = {
          title: "Rate Crafting Coach",
          message: "If you enjoy using Crafting Coach, please rate and review it.",
          cancelButtonLabel: "No, Thanks",
          laterButtonLabel: "Remind Me Later",
          rateButtonLabel: "Rate It Now"
        };
      }      
    )
  }

}

try private rateService in your constructor

Can you post your full error message? We can’t know what like it happened on without it.

My guess is one of your paths is wrong but it’s hard to say without your complete error

Interesting, so is complaining in the constructor, not about the import. No other error messages in terminal/command prompt?

Yeah, i don’t understand why

Ya super weird, the import is definitely there right? Do you have a github repository of this or anything? This one is a mystery to me.

Yep, the import is there, I’v just double checked everything, all the file locations, code, etc. Everything looks fine, I’m so confused. I don’t have a github repository for it, no.

Well if you want to share it on github I could take a look. Otherwise sorry, I really don’t know.

These are the main ones you need:

Okay, found the issue, it was quite simple, there was just no way to know it via the info you provided because you did not provide your folder structure. You do not have a folder named rate-service. Therefore your import is wrong. it’s just import { RateService } from '../../providers/rate-service' in your information page, and the same but one less level up in your app.module.

What IDE are you using? Because mine immediately caught this. I’d recommend moving to an IDE that understands modules, that will save you a lot of hardship.
image

Notice the red underline, then the message when I hover. That at least lets you know where to start looking, even if TypeScript’s compiler isn’t as helpful.

Also, you most likely don’t want to have RateService as a provider in your information component, you’ve already made it a provider in the root app module, that makes it available to everything in that module, which is everything.

Finally, just some extra tips you can what you wish with: WOAH your project could stand more modules. Right now you just have one gigantic app module. With an app as big as yours it’s helpful to organize features by modules, then import just those into your main module. See the angular documentation, tutorial, or style guide for info on that. Also you’ll want more providers, try to keep as much logic out of your components as possible.

Hi,

I knew it would be something simple hehe

I use Visual Studio Code, the import that is underlined in your’s wasn’t underlined in VSC.

So, if i don’t need a provider in the whole App (just one page), i don’t put it in the root app module just import it in the page i need it in?

Also, Thanks for the feedback, I’ll look into what you suggest and I will take it on board :slight_smile:

Two things are going on here: importing and declaring as a provider. You absolutely must import any type you use in every file you use it in.

As for where to declare providers, almost always you want to do it in the app module, so there is a single instance shared amongst all consumers. When you declare it at the component level, a new instance is created for each component, so if you do this:

@Component({providers: [FooService]})
export class BarPage {
  constructor(foo: FooService) {
    foo.thingy = 'hello';
  }
}

@Component({providers: [FooService]})
export class BazPage {
  constructor(foo: FooService) {
    console.log(foo.thingy);
  }
}

and you navigate from BarPage to BazPage, ordinarily one would think foo.thingy would be set to ‘hello’ in BazPage’s constructor. If you declare FooService only in the app module, that’s what would happen. But since you’ve declared it at the component level, BarPage and BazPage get different instances of FooService. This is very rarely desired.

1 Like

I would tweak this slightly and say you should do it at the module level you want to use it (https://angular.io/styleguide#!#07-03). If @CarlRyds were to take my advice and go a modular approach and have like an “information” module you could declare it as a provider there.

That keeps your code modular and reusable, instead of having one gigantic single app module.

But otherwise, yes, agree completely. But @CarlRyds you are correct in that if you only need it in one place that’s technically fine, you could just run into confusing behavior if you try to use it somewhere else, because as @rapropos says it will create a new copy instead of being a singleton as expected. And you certainly don’t need to do it in both your information component and app component, that leads to even more confusion.

(As a side note I’m surprised VSC doesn’t catch this for you, maybe try TypeScript Import Assistance - Visual Studio Marketplace. I use Webstorm, not only does it underline like that, but the way I fixed it was by deleting the import altogether, causing webstorm to ask me to hit “Alt + Enter” to auto import it. So I did and it put the right path in for me. Magic!

That’s a fair correction. Thanks.

If I had to guess, the lack of an underline on the invalid import would be because of this:

In my experience this will indeed cause all imports to be considered valid. Until it actually runs, of course.

Warning semi-advanced topic :grimacing:

Sorry, actually…this is wrong, if you declare the provider in any module it is application scoped. https://angular.io/docs/ts/latest/cookbook/ngmodule-faq.html#!#why-is-a-service-provided-in-a-feature-module-visible-everywhere

The proper answer in vanilla Angular 2 is you should do it at the highest component level you want it shared from https://angular.io/styleguide#!#07-03

However, since we don’t use the angular router, and can’t do lazy loading…this doesn’t really matter, we only have a single top level component. That means all services are application scoped…

You can have your providers in the root module or any other module, or in the app component…and it will all basically be the same. Wow…I don’t know how I feel about this. I’ve been back in Ionic 1 land for too long and hadn’t put all this together.

Looks like true modularity isn’t really an option in Ionic 2… :frowning:

1 Like

Check for the declarations and bootstrap

import { NgModule, ErrorHandler } from '@angular/core';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { RateService } from '../providers/rate-service/rate-service';

@NgModule({
  declarations: [
    MyApp,
    HomePage,
    RateService
  ],
  imports: [
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage,
    RateService
  ],
  providers: [{provide: ErrorHandler, useClass: IonicErrorHandler}]
})
export class AppModule {}

Regards :grin: