Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix 'No provider for service' error?

Tags:

angular

I get an error:

"Exception: Call to Node module failed with error: Error: Uncaught (in promise): Error: No provider for ServiceModuleService! Error: No provider for ServiceModuleService!"

Here is some code.

app.module.shared.ts:

import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { AppComponent } from './components/app/app.component'
import { ServiceModuleListComponent } from './components/service-module-list/service-module-list.component';
import { HeaderComponent } from './components/shared/header/header.component';
import { ServiceModuleService } from './components/shared/service-module.service';
import { ServiceModuleComponent } from './components/service-module/service-module.component';

export const sharedConfig: NgModule = {
    bootstrap: [AppComponent],
    declarations: [
        AppComponent,
        ServiceModuleListComponent,
        HeaderComponent,
        ServiceModuleComponent
    ],
    imports: [
        RouterModule.forRoot([
            { path: '', redirectTo: 'servicemodulelist', pathMatch: 'full' },
            { path: 'servicemodulelist', component: ServiceModuleListComponent },
            { path: '**', redirectTo: 'servicemodulelist' }
        ])
    ],
    providers: [ServiceModuleService]
};

app.module.client.ts:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { sharedConfig } from './app.module.shared';

@NgModule({
    bootstrap: sharedConfig.bootstrap,
    declarations: sharedConfig.declarations,
    imports: [
        BrowserModule,
        FormsModule,
        HttpModule,
        ...sharedConfig.imports
    ],
    providers: [
        { provide: 'ORIGIN_URL', useValue: location.origin },
        sharedConfig.providers
    ]
})
export class AppModule {
}

app.component.ts

import { Component } from '@angular/core';

@Component({
    selector: 'app',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent {
}

service-module.component.ts:

import { Component, Input } from '@angular/core';
import { ServiceModule } from '../shared/service-module.type';

@Component({
    selector: 'service-module',
    templateUrl: './service-module.component.html'
})
export class ServiceModuleComponent {
    @Input() serviceModule: ServiceModule

    constructor() {

    }
}

service-module-list.component.ts:

import { Component, OnInit } from '@angular/core';
import { ServiceModule } from '../shared/service-module.type';
import { ServiceModuleService } from '../shared/service-module.service';
import { ServiceModuleComponent }from '../service-module/service-module.component';

@Component({
    selector: 'service-module-list',
    templateUrl: './service-module-list.component.html'
})
export class ServiceModuleListComponent implements OnInit {
    serviceModules: ServiceModule[];

    constructor(private serviceModuleService: ServiceModuleService) {
    }

    ngOnInit() {
        this.serviceModuleService.getServiceModuleItems()
            .then(serviceModuleItems => {
                this.serviceModules = serviceModuleItems;
            });
    }
}

service-module.service.ts:

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/Rx';
import { ServiceModule } from './service-module.type';

@Injectable()
export class ServiceModuleService {
    constructor(private http: Http) { }

    getServiceModuleItems() {
        return this.http.get('api/ServiceModuleItems')
            .map(response => response.json() as ServiceModule[])
            .toPromise();
    }
}

service-module.type.ts:

    export class ServiceModule {
    idx: number;
    applicationName: string;
    isActive: boolean;
    description: string;
}

Basically at this point, on startup the app must display a list of entries I have on a SQL table, and the service calls an API to get that, but am stuck on this issue now with the error message.

like image 868
Anton Avatar asked Jun 09 '17 19:06

Anton


Video Answer


1 Answers

I dug into this syntax a bit more:

imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    ...sharedConfig.imports
],

The '...' here is the JavaScript spread operator. It ensures that the contents of the imports is added here and not the array itself. One of my colleagues explained it like this:

imports: [
  a,
  b,
  c,
  sharedConfig.imports
]

you end up with (which puts the array in)

imports: [a, b, c, [what_shared_config_has]]

instead of what you want (the values from the array)

imports: [a, b, c, what_shared_config_has]

So this needs to have the spread operator as well:

providers: [
    { provide: 'ORIGIN_URL', useValue: location.origin },
    ...sharedConfig.providers
]
like image 116
DeborahK Avatar answered Sep 27 '22 20:09

DeborahK