9

I decided to put LoginComponent, AuthService, LoggedInGuard inside a module called AuthModule:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AuthComponent } from './auth.component';
import { LoginComponent } from './components/login/login.component';

import { AuthService } from './services/auth/auth.service';
import { StorageService } from './services/storage/storage.service';
import { RequestService } from './services/request/request.service';

import { LoggedInGuard } from './guards/logged-in.guard';

@NgModule({
  imports: [
    CommonModule
  ],
  providers: [AuthService, LoggedInGuard],
  declarations: [AuthComponent, LoginComponent],
  exports: [AuthService, LoggedInGuard]
})
export class AuthModule { }

And I want to use only AuthService methods in the rest of the Application. And LoggedInGuard to protect non-public routes.

So I tried to import them in AppModule:

import { AuthModule } from './core/auth/auth.module';

@NgModule({
  declarations: [AppComponent, HomeComponent],
  imports: [
    BrowserModule,
    FormsModule,
    ReactiveFormsModule,
    HttpModule,
    AuthModule,
    RouterModule.forRoot(routes)
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

But in app.routes.ts LoggedInGuard is not available with this line of code:

import { LoggedInGuard } from './core/auth/auth.module'; 

It doesn't compile and it says:

...auth/auth.module has no exported member 'LoggedInGuard'

If I point it to its right place:

import { LoggedInGuard } from './core/auth/guards/logged-in.guard';

It compiles, but is showing the following runtime error:

Unexpected value 'AuthService' exported by the module 'AuthModule'

What do you please suggest me?

Thanks in advance.

Pasp Ruby
  • 837
  • 9
  • 21

1 Answers1

21

exports isn't for services. Adding the services to providers is enough. So remove the AuthService and AuthGuard from the exports.

What exports is for is for making components, pipes, directives, and other modules accessible to other modules. So you need to add the AuthComponent, and LoginComponent to that is you want to be able to use them in other modules.

@NgModule({
  imports: [
    CommonModule
  ],
  providers: [AuthService, LoggedInGuard],
  declarations: [AuthComponent, LoginComponent],
  exports: [AuthComponent, LoginComponent]
})
export class AuthModule { }

Also note that importing the AuthModule to the AppModule, only makes the components available to other components declared in the AppModule. Any other modules that want to use these components should import the AuthModule.

Paul Samsotha
  • 188,774
  • 31
  • 430
  • 651
  • While you are correct about how to make this work, the statement that "exports are not for services" is not true. Exports are for making any class available to the outside world. – Ben Richards Nov 09 '16 at 00:42
  • 1
    @BoyanKostadinov Do you mean file `export` or `@NgModule.exports`. If the latter, I'd like to see documentation on this. If the former, we are actually talking about the latter here :-P `@NgModule.providers` already makes it global to the outside world, in the application scoped sense – Paul Samsotha Nov 09 '16 at 00:45
  • I see what you mean now. You meant the "exports" array in the module metadata. I meant the "export" keyword. – Ben Richards Nov 09 '16 at 00:46
  • What about the services? Don't they must belong to a module? – Pasp Ruby Nov 09 '16 at 01:07
  • 1
    @PaspRuby They are in the `providers` array – Paul Samsotha Nov 09 '16 at 01:09
  • @peeskillet Thanks! But something is not that clear yet. How could I access AuthService.SomeMethod() (which is in AuthModule) from a component inside AppModule ? – Pasp Ruby Nov 09 '16 at 01:21
  • 1
    @PaspRuby You need to 1) import the class into the component class file 2) inject the service into the component's constructor. Adding it to the `@NgModule.providers` makes the service injectable for others who need it. – Paul Samsotha Nov 09 '16 at 01:23
  • awesome, @peeskillet ! By changing auth.module to: `@NgModule({ imports: [ CommonModule ], providers: [AuthService, LoggedInGuard], declarations: [LoginComponent], exports: [LoginComponent] }) export class AuthModule { }` But an error says `import { LoginComponent } from './core/auth/auth.module';`**auth.module has no exported member LoginComponent** – Pasp Ruby Nov 09 '16 at 01:36
  • 1
    You need to import from the component file. Why are you trying to import it from the module file? – Paul Samsotha Nov 09 '16 at 01:40
  • 1
    I think you are totally confusing the purpose of file `import`. It is only to be able to access the class/symbol in a different file. It nothing to do with how Angular handle components/services/or anything for that matter. – Paul Samsotha Nov 09 '16 at 01:42
  • Because I thought: If the LoginComponent belongs to AuthModule so LoginComponent should be 'available' only when I import its module. – Pasp Ruby Nov 09 '16 at 01:43
  • 1
    Yes it is available to use in _template_. There is no need to _file import_ the component into other component files. These are two completely different concepts – Paul Samsotha Nov 09 '16 at 01:47
  • but if I set "exports: []" removing LoginComponent from in AuthModule, I still can access LoginComponent from a different module by referencing its real path. Doesn't NgModules provide isolation of what is private (not exported) ? – Pasp Ruby Nov 09 '16 at 01:55
  • 1
    No. File import/export is completely different concept from Angular `@NgModule.imports/exports`. These are completely different concepts and have no relation _whatsoever_. `@NgModule` is to make things available for the application, while file import/export gives access from one file to another file. File excess is not a concept that is related to Angular. It is Javascript/typescript. – Paul Samsotha Nov 09 '16 at 01:59
  • Thanks very much @peeskillet . I'm almost there. What do you exactly mean when you say "@NgModule is to make **things available for the application**"? – Pasp Ruby Nov 09 '16 at 02:10
  • 2
    To make component/directives/pipes able to be used in templates... to make services injectable... all these concepts are related to the Angular _application_, not _file related things_ – Paul Samsotha Nov 09 '16 at 02:12
  • Perfect explanation. Thanks very much! – Pasp Ruby Nov 10 '16 at 18:03