Search code examples
javascriptangularservice

Why won't my Service inject properly into a component in Angular?


The structure of my Angular App (and relevant portions) is as follows:

app/app.module.ts

import { DbService } from './db.service'


const APP_CONTAINERS = [
  DefaultLayoutComponent,
  DefaultHeaderComponent,
];

@NgModule({
  declarations: [ ...APP_CONTAINERS ],
  providers: [ DbService ]

})

export class AppModule {}

app/containers/default-layout.component.ts

import { Component, HostBinding, Inject } from '@angular/core';
import { DbService } from '../../db.service';
import { navItems } from './_nav';
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})

@Component({
  selector: 'app-dashboard',
  templateUrl: './default-layout.component.html'
})
export class DefaultLayoutComponent {
  @HostBinding('class.c-app') cAppClass = true;

  constructor(private DbService: DbService) {}

  async ngOnInit() {
    console.log('working') 
   }
}

I use this same service successfully in other portions of my site but they all have specific module.ts files. I followed the Angular tutorial to get to where I am but I am still getting errors no matter how I try to inject this service.

I also tried using @Inject in my constructor but received the same error.

I currently receive the following error in my console:

ERROR Error: Uncaught (in promise): NullInjectorError: R3InjectorError(e)[e -> e -> e -> e]: 
  NullInjectorError: No provider for e!
NullInjectorError: R3InjectorError(e)[e -> e -> e -> e]: 
  NullInjectorError: No provider for e!

Solution

  • I use this same service successfully in other portions of my site but they all have specific module.ts files

    So it is unclear how you divide your modules. It doesn't look from the module file like that component is in the module that provides the service. The service has to be in the providers for the injection tree where the component resides. If that module file is for a different module, then the injector has to way to know what you want provided for the service.

    One solution would be to add it in the providers for your component. That would get a different instance of the service than in your other modules however:

    @Component({
      selector: 'app-dashboard',
      templateUrl: './default-layout.component.html',
      providers: [DbService]
    })
    export class DefaultLayoutComponent {
    

    You could also add it to the providers for the module your component resides in, but that would get a different instance as well.

    I think the best way would be to define the service so that it should be provided in the root module. This way you don't have to add it in the providers anywhere, angular will automatically add it to the root module's providers when it is required. That leads to what Octavian was saying in his comment. I think you just put this code incorrectly in the component instead of the service. Move this to the service and remove the service from the providers arrays in your module(s):

    @Injectable({
      providedIn: 'root'
    })