Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular Inject Service into Service : No Provider

I have two services in Angular:

MonitoringService.service.ts:

import { ClientAppSettingService } from './clientAppSettings.service';
import { Injectable, Inject } from '@angular/core';

@Injectable()
export class MonitoringService
{
  constructor(private _clientAppSettingService: ClientAppSettingService)
  {
    this.getclientAppSettings();
  }
  getclientAppSettings(): any {
    this._clientAppSettingService.getConfig().subscribe(result => {
    this.data = result;
    }, error => console.error(error));
  }

and ClientAppSetting.service.ts:

import { Injectable, Inject } from '@angular/core';
import { AppSettingsClient } from '../models/appSettingsClient';
import { HttpClient } from '@angular/common/http';

@Injectable()
export class ClientAppSettingService {
  appUrl: string = "";
  constructor(private http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
    this.appUrl = baseUrl;
  }
  getConfig() {
    return this.http.get<AppSettingsClient>(this.appUrl + 'api/ClientAppSettings/Get');
  }
}

This is app.module.ts:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { RouterModule } from '@angular/router';
import { ClientAppSettingService } from './services/clientAppSettings.service';
import { HomeService } from './services/home.service';
import { AppComponent } from './app.component';
import { MonitoringService } from './services/monitoring.service';
import { HomeComponent } from './home/home.component';
import { EmbedReportComponent } from './embedReport/embedReport.component';
import { BaseComponent } from './base.component';
@NgModule({
  declarations: [
    AppComponent,
    HomeComponent,
    EmbedReportComponent,
    BaseComponent
  ],
  imports: [
    BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),
    HttpClientModule,
    FormsModule,
    RouterModule.forRoot([
      { path: '', component: HomeComponent, pathMatch: 'full' },
      { path: 'report', component: EmbedReportComponent }
    ])
  ],
  providers: [
    ClientAppSettingService,
    HomeService,
    ReportService,
    MonitoringService
    ],
  bootstrap: [AppComponent]
})
export class AppModule { }

I followed this , which says that you need to provide service in the provider of NgModule.

I also followed this, which says

Make sure you declare a provider for ClientAppSettingService before you declare a provider for MonitorningService

I also tried adding @Inject in my constructor as below:

constructor( @Inject(ClientAppSettingService) _clientAppSettingService: ClientAppSettingService)

However, I still receive error regarding No Provider:

ERROR Error: Uncaught (in promise): Error: No provider for ClientAppSettingService! (MonitoringService -> ClientAppSettingService) Error: No provider for ClientAppSettingService! (MonitoringService -> ClientAppSettingService)

Additional Information:

I have a base.component.ts which calls the MonitoringService:

import { MonitoringService } from './services/monitoring.service';
import { Component, ReflectiveInjector, OnInit } from '@angular/core';

@Component({
  template: ''
})
export class BaseComponent
{
  constructor(private _monitoringService: MonitoringService)
  {
    const injector = ReflectiveInjector.resolveAndCreate([
      MonitoringService
    ]);
    this._monitoringService = injector.get(MonitoringService);
  }

Then I extent other components with Base.component.ts to use the MonitorningService as below. For example home.component.ts uses MonitoringService as below:

import { Home } from '../models/home';
import { BaseComponent } from '../base.component';
import { MonitoringService } from '../services/monitoring.service';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html'
})

export class HomeComponent extends BaseComponent implements OnInit
{
  home: Home;

  constructor(private homeService: HomeService, private _monitorningService: MonitoringService)
  {
    super(_monitorningService);
  }
like image 478
SillyPerson Avatar asked Jul 02 '18 08:07

SillyPerson


People also ask

Can you inject a service into a service Angular?

Angular provides the ability for you to inject a service into a component to give that component access to the service. The @Injectable() decorator defines a class as a service in Angular and allows Angular to inject it into a component as a dependency.

What's the best way to inject one service into another in Angular?

We must tell Angular to instantiate Service1 to be available (instatiated) before Service2. Hence, we declare it as a provider into our module. In this small example application, we have only one module, the app.

Can we use service without injectable?

If you want to use angular services (and Http is an angular service) you must inject them as I told above as a constructor attribute to another service / component , which means if you want to use Http you need to have your service injectable. So the answer is no, you can't do it in a nice way.

What is Nullinjector () in Angular?

Angular Creates the Module Injector tree when the Application starts. At the top of the Module Injector tree, Angular creates an instance of Null Injector . The Null Injector always throws an error unless we decorate the dependency with the Optional decorator.


1 Answers

Let me explain it a little. You have two layers one layer is your component and the other layer is your module. What you can do is provide the ClientAppSettingService into the component:

 @Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  providers: [ClientAppSettingService]
})

You have to remove it from your module and keep the other one there. Keep in mind that everywhere where you want to inject your service you have to provide it into the component.

like image 171
Swoox Avatar answered Oct 12 '22 00:10

Swoox