Angular 2 - No provider for Service

15,436

Solution 1

It was a configuration issue after all, and a completely elusive one at that.

Per the ang2 style guide, I had my main.ts one folder up from my main app folder, and in systemjs.config I had to declare the main for app as '../main.js'. When I moved the main file to the root app folder and changed the package declaration in systemjs to 'main.js' it worked.

The odd thing is everything else worked, right up until I try to utilize hierarchical dependency injection.

Solution 2

To All future readers - and this is correct for angular 2.0.0 rc-4:

make sure that you follow the below folder structure:

root:
index.html
package.json
systemjs.config.js
tsconfig.json (if using TypeScript) 
typings.json
app (folder):
 - main.js (the root script for your app)
 - app.component.js (the root component for the entire app)

This is crucial for the hierarchical injection to properly scope and identify providers.

Also, and this is very important - if still encountering problems and you are using TypeScript or any other transpiled language- delete any artifacts which your transpiler produces for every associated class in the problematic object graph - this, and the OP's answer eventually helped in my case (*.map.js and *.js files deleted and re-transpiled).

Solution 3

For me, some references to the "services" folder were "Services". When I made them all "services" (lower case), it worked.

For example:

import {ApiService} from "./Services/api.service";

didn't work, but this worked:

import {ApiService} from "./services/api.service";

Solution 4

Injecting something on the app level is done in bootstrap:

main.ts:

import { TestService } from '../shared/test.service';

bootstrap(AppComponent, [
  APP_ROUTER_PROVIDERS, TestService
])
Share:
15,436
Daynil
Author by

Daynil

Updated on June 17, 2022

Comments

  • Daynil
    Daynil almost 2 years

    I've been trying to troubleshoot a strange problem with angular 2 where it isn't detecting my provider declaration, but nothing is working. I can't even replicate it in plunkr.

    I'm using angular 2 rc 3 with router 3.0 alpha.8.

    Error message is: ORIGINAL EXCEPTION: No provider for TestService!

    app.routes.ts:

    import { provideRouter, RouterConfig } from '@angular/router';
    
    import { HomeComponent } from './app/home/home.component';
    import { LogInComponent } from './app/log-in/log-in.component';
    import { SignUpComponent } from './app/sign-up/sign-up.component';
    
    export const routes: RouterConfig = [
      { path: '', component: HomeComponent },
      { path: 'log-in', component: LogInComponent },
      { path: 'sign-up', component: SignUpComponent }
    ];
    
    export const APP_ROUTER_PROVIDERS = [
      provideRouter(routes)
    ];
    

    main.ts:

    import { bootstrap }    from '@angular/platform-browser-dynamic';
    import { enableProdMode } from "@angular/core";
    
    import { AppComponent } from './app/app.component';
    import { APP_ROUTER_PROVIDERS } from './app.routes';
    
    // enableProdMode();
    
    bootstrap(AppComponent, [
      APP_ROUTER_PROVIDERS
    ])
    .catch(error => console.log(error));
    

    app/app.component.ts:

    import { Component } from '@angular/core';
    import { ROUTER_DIRECTIVES } from '@angular/router';
    
    import { TestService } from './shared/test.service';
    
    @Component({
      selector: 'my-app',
      template: `
        <div id="menu">
          <a [routerLink]="['/sign-up']"><button>Sign Up</button></a>
        </div>
        <router-outlet></router-outlet>
      `,
      directives: [ROUTER_DIRECTIVES],
      providers: [TestService]
    })
    export class AppComponent {
    
      constructor() { }
    
    }
    

    app/sign-up/sign-up.component.ts:

    import { Component } from '@angular/core';
    import { ROUTER_DIRECTIVES } from '@angular/router';
    
    import { TestService } from '../shared/test.service';
    
    @Component({
      selector: 'sign-up',
      template: `<h1>Sign up!</h1>`,
      directives: [ROUTER_DIRECTIVES]
    })
    export class SignUpComponent {
      constructor(private testService: TestService) {
        this.testService.test('works?');
      }
    
    
    }
    

    app/shared/test.service.ts:

    import { Injectable } from '@angular/core';
    
    @Injectable()
    export class TestService {
    
      constructor() { }
    
      test(message: string) {
        console.log(message);
      }
    
    }
    

    So, I'm providing the testservice in the base component (app.component.ts) because I want all my components to access the same instance. However, when I navigate to sign-up, I get the no provider for testservice error. If I provide the TestService within the sign-up component, this then works:

    import { Component, OnInit } from '@angular/core';
    import { ROUTER_DIRECTIVES } from '@angular/router';
    
    import { TestService } from '../shared/test.service';
    
    @Component({
      selector: 'sign-up',
      template: `<h1>Sign up!</h1>`,
      directives: [ROUTER_DIRECTIVES],
      providers: [TestService]
    })
    export class SignUpComponent implements OnInit {
      constructor(private testService: TestService) { }
    
      ngOnInit() { }
    
    }
    

    However, I need the same instance accessible throughout my app, so how can I inject this at the main component level?

    I even tried replicating this app-level service providing with plunkr with the same version of everything, but it doesn't seem to give me the same error...

    http://plnkr.co/edit/5bpeHs72NrlyUITCAJim?p=preview