Question

Angular Dependency Injection: Fixing 'No Provider for NameService'

typescriptangularsystemjs

Question

I am trying to inject a service class into an Angular component, but Angular keeps throwing a "No provider for NameService" error.

Here is my code:

/// <reference path="../typings/angular2/angular2.d.ts" />

import { Component, View, bootstrap, NgFor } from "angular2/angular2";
import { NameService } from "./services/NameService";

@Component({
    selector: 'my-app',
    injectables: [NameService]
})
@View({
    template:
        '<h1>Hi {{name}}</h1>' +
        '<p>Friends</p>' +
        '<ul>' +
        '   <li *ng-for="#name of names">{{name}}</li>' +
        '</ul>',
    directives: [NgFor]
})
class MyAppComponent {
    name: string;
    names: Array<string>;

    constructor(nameService: NameService) {
        this.name = 'Michal';
        this.names = nameService.getNames();
    }
}

bootstrap(MyAppComponent);
export class NameService {
    names: Array<string>;

    constructor() {
        this.names = ["Alice", "Aarav", "Martín", "Shannon", "Ariana", "Kai"];
    }

    getNames() {
        return this.names;
    }
}

What causes this error, and how should the service be registered so Angular can inject it into the component correctly?

Short Answer

By the end of this page, you will understand what Angular's "No provider" error means, how Angular dependency injection works, where services must be registered, and how to correctly inject a service like NameService into a component.

Concept

Angular uses a system called dependency injection (DI) to create and supply objects such as services.

When you write this constructor:

constructor(nameService: NameService) {}

Angular reads it as: "This component depends on an instance of NameService."

Angular can only create that service if it knows how to provide it. That is what a provider does.

A provider is Angular's registration record for a service. Without a provider, Angular does not know:

  • whether the service is allowed to be created
  • where it should be created
  • which instance should be shared

That is why Angular throws:

No provider for NameService

In older Angular 2 syntax, services were registered using providers or in very early builds appInjector. Using the wrong metadata property such as injectables can cause Angular to ignore the service registration entirely.

In your code, the main issue is that injectables is not the correct way to register the service for the Angular version expected by this pattern. Angular therefore sees the constructor dependency, tries to resolve NameService, and fails.

This matters in real projects because services are commonly used for:

  • API calls
  • shared business logic
  • configuration
  • caching
  • state management
  • logging and error handling

If service registration is wrong, entire parts of the app fail at runtime.

Mental Model

Think of Angular dependency injection like a tool desk in a workshop.

  • Your component is a worker.
  • NameService is a tool.
  • Angular is the person managing the tool desk.

When the worker says, "I need a NameService", Angular checks the desk.

  • If the tool is registered there, Angular hands it over.
  • If the tool is not registered, Angular says: "No provider for NameService."

So the problem is usually not the constructor itself. The problem is that Angular's tool desk does not know about that tool yet.

Take Quiz

Syntax and Examples

The core idea is:

  1. Create a service class.
  2. Register it with Angular using a provider.
  3. Request it in the constructor.

Service

export class NameService {
    private names: string[] = ["Alice", "Aarav", "Martín", "Shannon", "Ariana", "Kai"];

    getNames(): string[] {
        return this.names;
    }
}

Component with provider registration

import { Component, View, bootstrap, NgFor } from "angular2/angular2";
import { NameService } from "./services/NameService";

@Component({
    selector: 'my-app',
    providers: [NameService]
})
@View({
    template:
        '<h1>Hi {{name}}</h1>' +
        '<p>Friends</p>' +
        '<ul>' +
        '  <li *ng-for="#person of names">{{person}}</li>' +
        '</ul>',
    directives: [NgFor]
})
class MyAppComponent {
    name: string;
    names: string[];

    constructor(nameService: NameService) {
        this.name = 'Michal';
        this.names = nameService.getNames();
    }
}

bootstrap(MyAppComponent);

What changed?

  • injectables: [NameService] became providers: [NameService]
  • the loop variable was renamed from name to person to avoid confusion with the component property name

Alternative: register at bootstrap

Another common pattern is to register the service at application startup:

bootstrap(MyAppComponent, [NameService]);

That makes the service available from the root level.

Why this works

When Angular sees providers: [NameService], it knows how to create NameService. Then when it reaches this constructor:

constructor(nameService: NameService)

it can successfully create and pass in the service instance.

Step by Step Execution

Consider this simplified version:

class NameService {
    getNames() {
        return ["Alice", "Kai"];
    }
}

@Component({
    selector: 'my-app',
    providers: [NameService]
})
class MyAppComponent {
    names: string[];

    constructor(nameService: NameService) {
        this.names = nameService.getNames();
    }
}

What happens step by step

  1. Angular starts creating MyAppComponent.
  2. Angular reads the constructor and sees that it needs a NameService.
  3. Angular checks the component's providers array.
  4. It finds NameService there.
  5. Angular creates an instance of NameService.
  6. Angular passes that instance into the constructor.
  7. The constructor runs nameService.getNames().
  8. The returned array is stored in this.names.
  9. The template renders the list.

What happens when the provider is missing

If providers: [NameService] is not present, step 3 fails.

Angular looks for a registered provider, cannot find one, and throws:

No provider for NameService

That means the dependency request worked, but the service registration did not.

Real World Use Cases

Dependency injection and service providers are used everywhere in Angular apps.

API services

constructor(userService: UserService) {}

A service fetches users from a backend.

Shared application state

A cart service can be shared across product pages and checkout pages.

Validation and formatting

A service can centralize logic like date formatting, currency conversion, or form validation.

Authentication

An AuthService might store login status, tokens, and user profile information.

Logging and error reporting

Apps often inject a logging service to capture errors consistently.

In all of these cases, the service must be properly registered with Angular before it can be injected.

Take Quiz

Real Codebase Usage

In real Angular codebases, developers usually register services at the appropriate scope.

Root-level shared services

Used when one instance should be shared across the app.

Examples:

  • authentication
  • API clients
  • configuration
  • global state

In older Angular versions this could be done at bootstrap:

bootstrap(MyAppComponent, [NameService]);

Component-level services

Used when each component should get its own instance.

@Component({
    selector: 'user-panel',
    providers: [UserPanelService]
})

Common patterns

Guard clauses

Services often validate input early:

getUser(id: number) {
    if (!id) {
        throw new Error('User id is required');
    }
}

Wrapping reusable logic

Instead of putting data logic in the component:

this.names = ["Alice", "Kai"];

developers move it into a service so multiple components can reuse it.

Separation of concerns

  • component: handles UI
  • service: handles data and business logic

This keeps files easier to test and maintain.

Common Mistakes

Here are common reasons beginners see "No provider" errors.

1. Using the wrong metadata property

Broken:

@Component({
    selector: 'my-app',
    injectables: [NameService]
})

Correct:

@Component({
    selector: 'my-app',
    providers: [NameService]
})

If Angular does not recognize the property, the service is never registered.

2. Forgetting to register the service anywhere

Broken:

constructor(nameService: NameService) {}

with no providers and no bootstrap registration.

Fix: add the service to providers or register it at bootstrap.

3. Importing the wrong class path

If the import path is wrong, Angular may not be using the class you think it is.

import { NameService } from "./services/NameService";

Always verify the path and exported class name.

4. Confusing template variable names with component property names

Your template uses #name of names while the component also has a name property.

This is not the provider error, but it can be confusing.

Better:

<li *ng-for="#person of names">{{person}}</li>

5. Putting too much logic in the component

Beginners sometimes create service classes but still hardcode everything in the component. If the logic belongs in a service, keep it there.

6. Assuming TypeScript type annotations create objects

This only declares the type:

constructor(nameService: NameService)

It does not create the service by itself. Angular still needs a provider.

Comparisons

Here are some useful comparisons around Angular service injection.

ConceptWhat it doesWhen to use it
providers: [NameService]Registers a service for dependency injectionWhen the component or its children need the service
bootstrap(MyAppComponent, [NameService])Registers a root-level serviceWhen the whole app should share one instance
Constructor parameter nameService: NameServiceRequests the dependencyWhen the component needs to use the service
Plain import onlyMakes the class available in the fileNot enough for DI by itself

Import vs provider

import { NameService } from "./services/NameService";

This only tells TypeScript where the class is.

providers: [NameService]

This tells Angular to create and supply it.

Component-level vs root-level provider

ScopeResult
Component-level providerEach component subtree can get its own instance
Root-level providerOne shared instance across the app

Service class vs regular helper function

OptionBest for
Service classShared state, injected dependencies, reusable app logic
Helper functionSmall stateless utility logic
Take Quiz

Cheat Sheet

// 1. Create the service
export class NameService {
    getNames(): string[] {
        return ["Alice", "Kai"];
    }
}
// 2. Register the service in the component
@Component({
    selector: 'my-app',
    providers: [NameService]
})
class MyAppComponent {
    constructor(nameService: NameService) {}
}
// 3. Or register it at bootstrap/root level
bootstrap(MyAppComponent, [NameService]);

Rules to remember

  • import does not register a service for DI.
  • Angular can only inject services that have a provider.
  • providers is the key Angular looks for.
  • Constructor injection requests dependencies.
  • Root registration shares one instance more broadly.
  • Component registration can create local instances.

Common error

No provider for SomeService

Usually means:

  • the service was not added to providers
  • the wrong metadata key was used
  • the service was registered in the wrong place
  • the import is incorrect

Good cleanup tip

Avoid reusing names like name both as a component field and a loop variable.

FAQ

Why does Angular say "No provider for NameService"?

Because Angular sees that the component wants a NameService, but it cannot find a registered provider telling it how to create one.

Is importing the service enough?

No. Importing only makes the class available in the file. You must also register it as a provider.

Should I use providers in the component or at bootstrap?

Use component-level registration when you want a local instance. Use bootstrap or root-level registration when the service should be shared more widely.

What is the difference between a provider and a service?

A service is the class itself. A provider is Angular's registration that tells the DI system how to supply that service.

Why is injectables not working here?

Because Angular expects provider registration using the correct API for that version. If the metadata key is not recognized, Angular ignores it.

Can a component work without dependency injection?

Yes, but DI is the standard Angular pattern for reusable services and shared logic.

Does each component get a new service instance?

It depends on where the provider is registered. Component-level registration can create separate instances, while root-level registration usually shares one instance.

Take Quiz

Mini Project

Description

Build a small Angular component that displays a list of names from a service. This project demonstrates the full dependency injection flow: defining a service, registering it correctly, injecting it into a component, and rendering the returned data in the template.

Goal

Create a component that injects NameService and shows a list of names without triggering a provider error.

Requirements

  • Create a NameService class that returns an array of names.
  • Register the service so Angular can inject it.
  • Inject the service into a component constructor.
  • Store the returned names in a component property.
  • Render the names in the template using NgFor.
Take Quiz

Keep learning

Related questions

View more