how to extend service with dependencies in angular 2

angular 6 service inheritance
angular inject service without constructor
angular service inheritance
extend service angular
angular multiple instances of service
angular injectiontoken
dependency injection angular
angular useexisting

I have a parent service which has some dependencies like

@Injectable()
export class ParentService{
  constructor(private http:Http, private customService:CustomService){}
}

and I want to extend the service

@Injectable()
export class ChildService extends ParentService{
  constructor (){
    super(??) <= typescript now asking to enter two parameters according to ParentServie's constructor
  }
}

Edit-----------------

@Injectable()
export class ParentService{
  constructor(private http:Http, private customService:CustomService){}
  get(){this.http.get(...)}
}

@Injectable()
export class ChildService extends ParentService{
  constructor (private http:Http, private customService:CustomService){
    super(http, customService)
  }
}

Then I can use in components?

export class Cmp {
  constructor(private childService:ChildService){
    this.childService.get()
  }
}

The parameters of the super class need to be repeated and passed to the super call:

@Injectable()
export class ChildService extends ParentService{
  constructor (http:Http, customService:CustomService){
    super(http, customService);
  }
}

There are some "hacks" to work around like Inheritance and dependency injection

Dependency injection in action, Nested service dependencies · Limit service scope to a component subtree This section explores many of the features of dependency injection (DI) in Angular. useFactory: runnersUpFactory(2), deps: [Hero, HeroService] } ] }) export class @Injectable({ providedIn: 'root' }) export class DateLoggerService extends  There are advantages to that approach if your service has dependencies. Service Dependencies. As soon as you add even one dependency to your service, you need to also add it to your tests. In case of isolated tests, you will need to pass an instance of an injectable dependency class into the constructor of your service instantiation.

Simply make base service... non-@Injectable()! For example, you need to supply a method to retrieve user profile in LoginService. This method will be different for different instances of LoginService, and parent class must not know anything about where from this method came: it can be lambda, it can be exported function, it can be a method of another service. To achieve this, you can declare parent service which Parent service:

// Don't annotate it with @Injectable() ! It's a simple class.
export abstract class BaseLoginService {
  constructor(
    // This won't be injected automatically, 
    // child class must call super() and provide value for this argument.
    // Note: it's private, can't be accessed outside of BaseLoginService class
    private http: HttpClient,
    // Method used to retrieve user profile
    private profileGetter: () => Observable<UserDetails>, 
    private router: Router
  ) {
    this.profileGetter().subscribe(); // Do something with this method
  }

Then extend it in child class:

// Child class must be annotated with @Injectable(),
// if you don't need to extend it further
@Injectable() 
export class LoginService extends BaseLoginService {

  constructor(
    // Note: no public/private/protected here - "http"
    // will be just an argument
    http: HttpClient, 
    private profileService: ProfileService, // This is the private field of LoginService class
    router: Router,
    // Some service used by LoginService class, parent class BaseLoginService
    // doesn't need to know about SomeOtherService
    private someOtherService: SomeOtherService
  ) {
    super(
      http,
      // Need lambda here to capture profileService instance. If
      // profileService.getUserDetailsMethod doesn't use instance
      // fields or methods, then we can simply write 
      // "profileService.getUserDetailsMethod" (without quotes, obviously).
      () => profileService.getUserDetailsMethod(), 
      router
    );
    this.someOtherService.doSomething(); // Custom initialization code
  }

Note: in providers section of module specify LoginService instead of parent BaseLoginService:

providers: [
  LoginService,

and use it in component classes:

export class LoginComponent implements OnInit {
  constructor(
    private loginService: LoginService
  ) {
  }

If you need to use parent service (e.g. in shared components which only need functionality from parent service class), then provide BaseLoginService this way:

providers: [
  {provide: BaseLoginService, useExisting: LoginService}, // For those components which need functionality from base class only
  LoginService, // Still need this one for those components which need functionality from child class

Singleton services, A singleton service is a service for which only one instance exists in an app. In the following example, the optional, injected UserServiceConfig extends the  In Angular you are unable to inject an instance of a service via 'provider' into another service. Instead, all the services would share the same instance. This is usually fine; however, if you want your BaseService to do more, such as handle errors, check if the call was successful, then store the result so your service can grab, then

If you make the DI services in the abstract class protected and omit the constructor in the subclass, then the services are available in the subclass.

Making all angular services extend a single base service, In Typescript/Angular 6 (2+), is it considered a good practice to have a base abstract http service from which derives all the application services? for example: //  Next, we extend the component's constructor to ask for dependency of type data service by adding a constructor parameter with a type annotation for data service. The type annotation is where the magic happens. With this, we tell Angular's dependency injection to give us an instance of whatever it knows as data service.

Angular How-to: Simplify Components with TypeScript Inheritance , In this example, we have 2 services that are used in the base class and are assigned using dependency injection. base.component.ts. @  Dependency Injection in Angular Dependency injection has always been one of Angular’s biggest features and selling points. It allows us to inject dependencies in different components across our applications, without needing to know, how those dependencies are created, or what dependencies they need themselves.

Child extends Parent dependecy not working · Issue #5155 · angular , I have parent with injected http service: import {Inject, Injectable, Component} import {Inject, Injectable, Component} from 'angular2/angular2'; import {Http} But actually parent dependencies is not initalized for extends. 2. Typescript. If you did not use Angular CLI, but you are using Typescript version 2.1 or greater, then you don't have to take any additional actions. Otherwise 3. Plain Javascript. If you don't use Angular CLI or Typescript, then you can just import a polyfill into your project. There are plenty out there and here are a few ones:

Dependency-Injection With Sub-Classed Services In Angular 2 Beta 3, Dependency-Injection With Sub-Classed Services In Angular 2 Beta 3. By Ben Nadel on February 12, 2016 Extend the Greeter class. Dismiss Join GitHub today. GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.

Comments
  • no, the constructor misses the parameters. Angular2 DI reads from the constructor parameters what dependencies it has to pass to a component. ChildService won't get passed anything in because it doesn't have constructor parameters. super(http, customService) is invalid because http and customService are not known in the sub class.
  • sorry forgot to add the paramenters to child components constructor. no correct?
  • This should work. It's similar to what I showed in my answer but now there are also overridden fields http and customService in the ChildService as well.
  • Hey, how aboust skipping private keyword in ChildService constructor? super() shall store them as properties
  • I can't get this to work without the ParentService not being @Injectable. Is that correct? Can't tell from the example, which seems to suggest that the ParentService can be @Injectable
  • I know it depends, but say you have N isolated entities in your app and they have to implement common methods. In your opinion, what is the recommended directory/place to store such classes?
  • @AndreiGătej I would suggest to start from asking yourself: why do you have such a question? Is there a code style you have to adhere to, but this aspect is not covered by it? If you're not working on this project alone, ask your project manager. In any way, if you are using some IDE, you can rename the directory later and IDE will automatically adjust all paths / includes in all places. Personally, I stored those base classes in the separate Angular project which was the shared dependency for others.