2

From what I can tell, I have followed the docs to create a CoreModule to provide my services in Angular 2.0.0. I also tried the suggestions from:

Provide core singleton services module in Angular 2

Angular2 RC5 ngModule: No Provider For NameService

To no avail. What is required to get services "wired up"? The error I am getting with the below code is:

No provider for AuthService!

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AppRoutingModule } from './app-routing.module';

//Modules/Components
import { AppComponent } from './app.component';
import { SignInModule } from './sign-in/signin.module';
import { CoreModule } from './services/core.module';

@NgModule({
    imports: [BrowserModule, AppRoutingModule, FormsModule,
        CoreModule, SignInModule],
    declarations: [AppComponent],
    bootstrap: [AppComponent],
})
export class AppModule { }

services/core.module.ts

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

// Services
import { SignalRService } from './signalr.service';
import { AuthService } from './auth.service';
import { UserSettingsService } from './user-settings.service';

@NgModule({
    providers: [SignalRService, AuthService, UserSettingsService]
})
export class CoreModule {
}

services/auth.service.ts

import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { SignalRService } from './signalr.service';
import { ISignInProvider } from '../sign-in/signin.interface';

@Injectable()
export class AuthService {
    constructor(private signalR: SignalRService, private router: Router) {
    }
..
}

sign-in/signin.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { GoogleSignInComponent } from './google-signin.component';

@NgModule({
    imports: [CommonModule, FormsModule],
    declarations: [GoogleSignInComponent],
    exports: [GoogleSignInComponent],
})
export class SignInModule { }

sign-in/google-signin.component.ts (I think this is where the error points to)

import { Component, AfterViewInit } from '@angular/core';
import { AuthService } from '../services/auth.service';
import { ISignInProvider } from './signin.interface';

@Component({
    moduleId: module.id,
    selector: 'google-signin',
    templateUrl: 'google-signin.component.html',
})
export class GoogleSignInComponent implements AfterViewInit, ISignInProvider     {
    constructor(private authService: AuthService) {
    }
}

The sign in component is in a feature module (SignInModule) but that is imported in the app module. I tried using forRoot in CoreModule but it seemed to have no effect. I couldn't get the SystemJS aliases working as suggested in the other question but am unsure why that would fix anything anyways.

Not using a CoreModule and putting the providers directly on AppModule doesn't work either. I haven't put them directly on the components as it is my understanding that it is bad practice. The sign-in component/module is not lazy loaded as far as I can tell, and it isn't part of the router (it is in the app component template).

Where is my error, or alternatively, what should I be doing differently?

Community
  • 1
  • 1
BradleyDotNET
  • 60,462
  • 10
  • 96
  • 117
  • Adding providers to components is not bad practices. It depends on what you actually try to accomplish. If you want to limit the scope of a service you have to either use a lazy loaded module or add it to a component. I don't see an error in your code. I'd expect it to work. – Günter Zöchbauer Nov 11 '16 at 07:16
  • @GünterZöchbauer I'm not trying to limit scope, those services are used throughout the application so I'm hoping to get this method working. If the only way to get it to work is to go the component route though, I will. – BradleyDotNET Nov 11 '16 at 07:26

1 Answers1

2

You have to add providers inside your signin.module.ts for SignalRService, AuthService and UserSettingsService.

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { GoogleSignInComponent } from './google-signin.component';

@NgModule({
    imports: [CommonModule, FormsModule],
    declarations: [GoogleSignInComponent],
    providers: [SignalRService, AuthService, UserSettingsService],
    exports: [GoogleSignInComponent],
})
export class SignInModule { }

Or you have to create one shared module which is having providers declaration for SignalRService, AuthService and UserSettingsService and you have to import this shared module inside your all other module.

//SharedModule

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { GoogleSignInComponent } from './google-signin.component';

@NgModule({
    imports: [CommonModule, FormsModule],
    providers: [SignalRService, AuthService, UserSettingsService]
})
export class SharedModule { }

//SignInModule

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';

import { SharedModule } from 'path to SharedModule';
import { GoogleSignInComponent } from './google-signin.component';

@NgModule({
    imports: [CommonModule, FormsModule, SharedModule],
    declarations: [GoogleSignInComponent],
    exports: [GoogleSignInComponent],
})
export class SignInModule { }
ranakrunal9
  • 13,320
  • 3
  • 42
  • 43
  • That should IMHO only be necessary for directives, components, and pipes, but not for services (didn't investigate too much myself yet in this area though). – Günter Zöchbauer Nov 11 '16 at 07:20
  • I believe the docs explicitly say to not re-import CoreModule... am I missing something or are the docs out of date? – BradleyDotNET Nov 11 '16 at 07:25
  • Providers (except for lazy loaded modules) are always added to the root DI scope, therefore importing a module in one place should be enough. It might be good practice to import a module in every module it depends to make the dependency obvious (to make directives available it required as mentioned) but I think it should not be necessary. AFAIR it's mentioned somewhere in the docs that if such a module is imported in multiple places, the providers are deduplicated and only one provider will be registered in the root scope. – Günter Zöchbauer Nov 11 '16 at 07:30
  • @GünterZöchbauer Apart from re-importing I noticed his `SharedModule` exports the services as well as putting them in the providers array, is that correct or should it just be in providers? Also, just to be double sure, this statement from the docs I linked is no longer true? "Only the root AppModule should import the CoreModule. Bad things happen if a lazy loaded module imports it." Or perhaps I need the imports because my other modules *aren't* lazy loaded? – BradleyDotNET Nov 11 '16 at 07:33
  • "Bad things" is that then are 2 instances because lazy loaded modules have their own root scope and lazy loaded components and services don't get the global instance but the instance from the lazy loaded module. I don't think providers need to be exported. I think that's only for directives, components, and pipes. I'm not too sure about this topic because I'm using Dart and there are no `NgModule`s – Günter Zöchbauer Nov 11 '16 at 07:35
  • @GünterZöchbauer Well, adding `CoreModule` to the import list for `SignInModule` *does* work. I am hoping someone can clarify as to if this is going to cause major problems down the road or not. The exports were not required. – BradleyDotNET Nov 11 '16 at 07:36
  • Weird. I agree, some additional insight would be great. – Günter Zöchbauer Nov 11 '16 at 07:39