Typescript cannot resolve injectable inside a component that worked in JS

I just updated my project from JS to TS, but it broke some parts, for example i had a component that imported a Config injectable and used it through all the component, the same injectable is used through all the app in different pages and components, for some reason it only breaks when in this component, here’s my code:

import {Component, Output, EventEmitter} from 'angular2/core';
import {IONIC_DIRECTIVES} from 'ionic-framework/ionic';
import {Config, DB} from '../../services/services';
@Component({
  selector: 'syncServ',
  templateUrl: 'build/components/sync/sync.html',
  directives: [IONIC_DIRECTIVES]
})
export class SyncComponent {
  public orders: number  = 0
  public visits: number  = 0
  public tryIt : boolean = true
  @Output() synced = new EventEmitter();
  constructor(
    public config: Config,
    public db: DB
  ) {}
  ngOnInit() {
    this.updateSyncUi()
  }
  updateSyncUi() {...}
  }
}

Here’s the console logs:

983455   error    EXCEPTION: Cannot resolve all parameters for 'SyncComponent'(undefined, DB). Make sure that all the parameters are decorated with Inject or have valid type annotations and that 'SyncComponent' is decorated with Injectable.
983455   error    STACKTRACE:
983455   error    Error: Cannot resolve all parameters for 'SyncComponent'(undefined, DB). Make sure that all the parameters are decorated with Inject or have valid type annotations and that 'SyncComponent' is decorated with Injectable.
  at NoAnnotationError.BaseException [as constructor] (http://localhost:8100/build/js/app.bundle.js:7773:24)
  at new NoAnnotationError (http://localhost:8100/build/js/app.bundle.js:8647:17)
  at _extractToken (http://localhost:8100/build/js/app.bundle.js:7747:16)
  at http://localhost:8100/build/js/app.bundle.js:7699:46
  at Array.map (native)
  at Array.map (http://localhost:8100/build/js/app.bundle.js:67:17028)
  at _dependenciesFor (http://localhost:8100/build/js/app.bundle.js:7699:20)
  at resolveFactory (http://localhost:8100/build/js/app.bundle.js:7591:25)
  at Object.resolveProvider (http://localhost:8100/build/js/app.bundle.js:7615:67)
  at Function.DirectiveProvider.createFromType (http://localhost:8100/build/js/app.bundle.js:18461:30)

Please a little help here, if i don’t fix this for tomorrow night the only option left is to revert my repo to before the update to Typescript and keep working with ES6. :cold_sweat:

Is config a service? Then maybe add it as a providers like so:

providers:[Config, DB]

in the app.ts (the first component you make where you initialize the Platform or inside the @App if you have it). If you did it correctly you should be able to just add the service in any constructor like you did.

If you added the providers inside the @App you should be able to use it anywhere you want. Never had a problem with that as of now.

this is mine:

import {IngredienteService} from ‘./services/ingredientes.service’;
import {RecetaService} from ‘./services/recetas.service’;

@App({
template: <ion-nav [root]="rootPage"></ion-nav>,
providers:[IngredienteService, RecetaService]
})

then I just add inside the constructor in any Class the service I want to use, exactly like you did.

It is in my app component’s providers array, its a global service, also the SyncComponent is in the CustomersPage’s directives array, the weird thing is that i had it working but after updating to Typescript it broke, the funny thing it is all over the app, in my login, masters, customers and statistics pages, but only breaks in this component, here’s my app component just in

// Dependencies
import {App, IonicApp, Platform} from 'ionic-framework/ionic';
import {
  Config,
  DB,
  MasterService,
  CustomerService,
  WalletService,
  RadialGraph
} from './services/services'
// Pages
import {
  LoginPage,
  MastersPage,
  CustomersPage,
  VisitDayPage,
  StatisticsPage,
  CustomerPage,
  OrderPage,
} from './pages/pages';
import {Type} from 'angular2/core';
// Components
import {BusyComponent, BusyCtrl} from './components/components';
@App({
  templateUrl: 'build/app.html',
  providers: [
    Config,
    DB,
    MasterService,
    CustomerService,
    WalletService,
    BusyCtrl,
    RadialGraph
  ],
  directives: [BusyComponent],
  config: {
    modalEnter: 'modal-pop-in',
    modalLeave: 'modal-pop-out',
  }
})
class MyApp {
  public user = 'user';
  public pages: {title: string, component: any, icon: string}[] = [
    { title: 'Maestros', component: MastersPage, icon: 'fa-list-alt' },
    { title: 'Dias visita', component: VisitDayPage, icon: 'fa-calendar' },
    { title: 'Clientes', component: CustomersPage, icon: 'fa-users' },
    { title: 'Estadisticas', component: StatisticsPage, icon: 'fa-line-chart' }
  ];
  public rootPage = CustomersPage;
  constructor(
    public app: IonicApp,
    public platform: Platform,
    public conf: Config,
    public db: DB
  ) {
    this.conf.tokenEmitter.subscribe((accessToken: {name: string}) => {
      this.user = accessToken.name
    })
  }
}

I don’t see anything wrong with your code mate. Maybe it is an Angular2 bug.

I don’t use Components though, maybe it is a Ionic bug thingy (eeing as @App is part of Angular2).

Try using @Page (don’t forget to import it from the ionic-framework/ionic) instead of a Component (don’t use the IONIC_DIRECTIVE because you don’t have too) and try again.

So the code in the page will be like this:
import { Output, EventEmitter} from ‘angular2/core’;
import {Page} from ‘ionic-framework/ionic’;

@Page({
  selector: 'syncServ',
  templateUrl: 'build/components/sync/sync.html'
})

I also think there’s nothing wrong, after all, all i did was refactor from ES6 (it WAS working) to Typescript, also i just added the IONIC_DIRECTIVES just in case.

Will i be able to use it as a component even if it is a page?

I don’t see any difference at all. I am mainly using what I learn from the tutorial and developer guide from angular2.io and everything has worked exactly the same. The only difference in the @App and @Page that I noticed is that I don’t have to add the IONIC_DIRECTIVES part. But who knows if there is something else behind the scenes that App and Page are doing unbeknownst to me. Just try it, if it doesn’t work just undo everything :wink:

So in your case it should be:

@Page({
  selector: 'syncServ',
  templateUrl: 'build/components/sync/sync.html'
})

Just wondering, does your Config Service have a @Injectable() in it?

Yes it does:

import {IonicApp, Alert, NavController} from 'ionic-framework/ionic';
import {Injectable} from 'angular2/core';
import {Subject} from 'rxjs/Subject';
import {DB} from './services';
import {BusyCtrl} from '../components/components';
// export class Table {
//   constructor(
//     public name: string = '',
//     public fields: string = ''
//   ){}
// }
@Injectable()
export class Config {
  public urlServerRest: string = ''
  public urlServerDb  : string   = ''
  public urlServerInfo: string = 'http://10.10.10.231:5436/adclientAccess'
  public to
  public accessToken: any
  constructor(
    public db: DB,
    public app: IonicApp,
    public busyCtrl: BusyCtrl
  ) {...}
}
1 Like

Well it doesn’t explode but also doesn’t work, the app loads correctly but the component that should be shown as a button with some numbers doesn’t show, i think the selector doesn’t work with the @Page annotation.

Ahh you’re right!!! Then I don’t know what to tell you bro.

Well, back to the JS version, thanks god for git :stuck_out_tongue:

1 Like

After playing a bit more i isolated the issue more, my Config service breaks when i use the BusyCtrl Injectable, weird thing is that it only breaks the Config service when i import it in the SyncServ component, could it be because it’s not a page but a component?

Maybe but I don’t think so. A @Page is just a @Component with some extra stuff with it. Just try and see how it does.

Fixed, i dunno actually why, i did another big refactor in my JS branch along with an update for the latest version of Ionic so i deleted my RefactorTypescript branch and translated all along, now it’s working.

Gracias hermano :smile:

1 Like