7
votes

I am using an application structure as mentioned below

index.ts
|-app.module.ts
|-app.component.ts
|--hero (directory)
   |-hero.module.ts
   |-hero.ts (Data Object)
   |-hero.service.ts
   |-hero.component.ts
   |-index.ts (this file exports data obj, service, component & module)
|--dashboard (directory)
   |-dashboard.module.ts
   |-dashboard.component.ts
   |-index.ts (this file exports module and component)

I wish to use hero service in dashboard component. Below is the code snippet I am using right now and its working as expected. But not sure if its a good practice.

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

import { Hero, HeroService } from '../hero/index';
import {Router} from '@angular/router';

@Component({
    moduleId: module.id,
    selector: 'my-dashboard',
    templateUrl: 'dashboard.component.html',
    styleUrls: ['dashboard.component.css']
})
export class DashboardComponent implements OnInit {
    heroes: Hero[] = [];

    constructor(private heroService: HeroService, private router: Router) { }

    ngOnInit(): void {
        this.heroService.getHeroes()
            .then(heroes => this.heroes = heroes.slice(1, 5));
    }

    gotoDetail(hero: Hero): void {
        let link = ['/detail', hero.id];
        this.router.navigate(link);
    }
}

I am curious to know if there is any way that I can access HeroService with reference to HeroModule rather than separately importing Hero object and HeroService from ../hero/index

2
One of the suggestion is to move hero.service.ts to shared package but I don't want to use that approach as logically this service belongs to hero package and only some part of it needs to be referred in some other package. - Mahesh
Imports are a TypeScript feature and unrelated to Angular. If you want to use a class as type in your code you have to import it (with or without Angular2). imports: [] in NgModule fulfill an entirely different purpose and this is an Angular2 feature. - Günter Zöchbauer
A very similar question was asked after yours which should lead you in the right direction: stackoverflow.com/questions/39621398/… - cmaynard
I totally understand your question, but other than components, directives, and pipes which can be placed directly on the template of a component, we need to have the source file for service, since typescript will throw an error. There is not getting around this problem until Angular/Typescript comeup with something like a proxy. - GingerBeer

2 Answers

18
votes

from Range.io

So far our problem is that we are creating two instances of the same services in different levels of the DI tree. The instance created in the lower branch of the tree is shadowing the one defined at the root level. The solution? To avoid creating a second instance in a lower level of the DI tree for the lazy loaded module and only use the service instance registered at the root of the tree.

import { NgModule, ModuleWithProviders } from '@angular/core';
import { CounterService } from './counter.service';

@NgModule({})
export class SharedModule {
  static forRoot(): ModuleWithProviders {
    return {
      ngModule: SharedModule,
      providers: [CounterService]
    };
  }
}

With this setup, we can import this module in our root module AppModule calling the forRoot method to register the module and the service.

...
import { SharedModule } from './shared/shared.module';

@NgModule({
  imports: [
    SharedModule.forRoot(),
    ...
  ],
  ...
})
export class AppModule {}
1
votes

Services are shared across the entire application, so if you put it into a module, other component has acces to it. However, you still need to import the classes Hero and HeroService in component where you use them.

Imports at the top of a class and Modules has just a differents purpose.