Injecting a service into a base class in Angular, but not in the sub-class, then utilizing the parent service in the sub-

When working with Angular 7 and Typescript, I have a base class that relies on multiple services and has around 40 subclasses. Instead of adding these services to each subclass constructor and passing them to super(), I am looking for a more efficient way to use the services in all subclasses.


export class ParentTool {

    constructor(type: string, public service1: Service1, public service2: Service2,public service3: Service3, public service4: Service4){}
}

export class ChildTool1 extends ParentTool {

    constructor(public service1: Service1, public service2: Service2,public service3: Service3, public service4: Service4) {

        super("tool1", service1, service2, service3, service4);
    }
}

export class ChildTool2 extends ParentTool {

    constructor(public service1: Service1, public service2: Service2,public service3: Service3, public service4: Service4) {

        super("tool2", service1, service2, service3, service4);
    }
}

Answer №1

When facing a similar issue, I opted for manual Dependency Injection (DI) by leveraging the injector service.

This static class was utilized to retain a reference of the injector service.

export class AppInjector {

  private static injector: Injector;

  static setInjector(injector: Injector) {
    AppInjector.injector = injector;
  }

  static getInjector(): Injector {
    return AppInjector.injector;
  }
}   

In the app module, I configured the injector service.

export class AppModule { 
  constructor(injector: Injector){
      AppInjector.setInjector(injector); // saving an injector reference 💾
  }
}

It is essential to store the service before initiating any DI operations (Dependency Injection).

Within the base component:

export class BaseComponent {
  protected utilitiesService: UtilitiesService; // 👈 service
  protected loggingService: LoggingService; // 👈 service

  constructor() {

      const injector = AppInjector.getInjector();

      this.utilitiesService = injector.get(UtilitiesService); // 🌟 DI
      this.loggingService = injector.get(LoggingService); // 🌟 DI
  }

}

The child class can now access all services injected by the injector class 🎉🎉

export class ChildComponent extends BaseComponent {
  constructor() {
    super();
  }
}

Check out the demo 🔥🔥

Answer №2

To enhance functionality, integrate an additional service and inject all necessary services accordingly. This can be achieved by including the new service in a subclass and passing it to the parent class using super.

@injectable()
export class ParentService {
    constructor(type: string, private service1: Service1, private service2: Service2,private service3: Service3, private service4: Service4){}
    executeService1(){
        this.service1.method1();
    }
}

export class parentTool {
    constructor(private parentService: ParentService){}
}

export class ChildTool1 extends parentTool {
    constructor(public parentService: ParentService) {
        super("tool1", parentService);
    }
}

export class ChildTool2 extends parentTool {
    constructor(public parentService: ParentService) {
        super("tool2", parentService);
    }
}

Answer №3

To prevent injecting all services in all child classes, you can utilize a global injector. For your specific scenario, the implementation would resemble the following:

import {Injector} from '@angular/core';
//other imports
export class mainTool {
  public serviceA: ServiceA
  public serviceB: ServiceB
  public serviceC: ServiceC
  public serviceD: ServiceD
      constructor(type: string, injector: Injector){
        this.serviceInjectA = injector.get(ServiceA);
        this.serviceInjectB = injector.get(ServiceB);
        this.serviceInjectC = injector.get(ServiceC);
        this.serviceInjectD = injector.get(ServiceD);
      }
  }

  export class ChildToolX extends mainTool {

      constructor(injector: Injector) {  
          super(injector);
          this.serviceA.someMethodCall()
      }
  }

  export class ChildToolY extends mainTool {

      constructor(injector: Injector) {  
          super(injector);
          this.serviceA.someMethodCall()
      }
  }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Angular 6: Sending Back HTTP Headers

I have been working on a small Angular Application for educational purposes, where I am utilizing a .net core WebApi to interact with data. One question that has come up involves the consistent use of headers in all Post and Put requests: const headers = ...

Angular 7's masonry overlay technique

I decided to implement a masonry design in my Angular application using the ngx-masonry package found here: https://www.npmjs.com/package/ngx-masonry However, I encountered an issue where some items are overlapping, as shown in this image: https://i.sstat ...

"What could be causing my React Native app to build without any issues even though the TypeScript compiler is throwing

Recently, I decided to explore TypeScript in combination with Expo. I took the time to set up linter and formatter integrations like typescript-eslint to help me catch errors while coding. Periodically, I run npx tsc to ensure my code compiles correctly an ...

Changing the type of value in a React select onChange

<Select options={options} value={selectedBusinessList} isMulti placeholder="Select Business" onChange={(value: any) => setSelectedBusinessList(value)} onInputChange={query => { if ...

Retrieving selected item values in Angular 2 using ng2-completer

Recently, I decided to experiment with a new autocompleter tool that is unfamiliar to me: https://github.com/oferh/ng2-completer. I successfully imported it and it seems to be functioning properly. My current goal is to retrieve the values of the selecte ...

Limiting the scope of TypeScript types to specific keys, such as Exact/DeepExact

After coming across this specific query on SO, I wanted to delve into creating an Exact type. My attempt at implementing something akin to a DeepExact seems to be close: // Desired type that should only accept Exact versions of type Opts = { firstName?: ...

Creating a Jasmine test for the event.target.click can be accomplished by defining a spec that

I need help creating a Jasmine test spec for the following method in my component. Here is my Component Method methodName(event): void { event.preventDefault(); event.target.click(); } I have started writing a test but don't fully cover event. ...

Guide on achieving horizontal scrolling in Ionic 3

Check out this image I have a list of 10 names in an ion-scroll, but they are appearing on separate lines like paragraphs. Below is my HTML code: <ion-scroll scrollX="true" style="width:100vw; height:50px" > <ion-row class="headerChip"& ...

Is there a method in Angular2+ to inherit constants from one and extend it into another constant?

Is there a way I can inherit or extend one const into another const? Parent.ts export const Vehicle = { 'Name': 'Honda', 'NoOfWheels': '4' } Child.ts import { Vehicle } from './Parent'; export const ...

The implementation of combineSlices in reduxjs/[email protected] is an essential feature for managing

I am struggling to figure out how to properly useAppSelector with LazyLoadedSlices: Here is the setup of my store // @shared/redux/store.ts // comment: https://redux-toolkit.js.org/api/combineSlices // eslint-disable-next-line @typescript-eslint/no-empty ...

How can you refer to the implementing class from an interface in TypeScript?

Delving into the Typescript type system, I am currently working on implementing the Fantasy Land Spec and encountered a hurdle while trying to implement the specification for Semigroup. The spec dictates that a Semigroup must follow the type definition ou ...

The error message "Property does not exist on type Object from subscribe" indicates that

When using forkJoin to make multiple http calls, I encountered the error error TS2339: Property 'data' does not exist on type 'Object' forkJoin(this.userservice.getUser(), this.userservice.getDashboard()).pipe( map(([userData, dash ...

What is the method for obtaining the union type of interface values (including string enums)?

How can I achieve the following ? Given : enum FooEnum1 { Foo = "foo", }; enum FooEnum2 { Foo = 1, }; interface FooInterface { foo1 : FooEnum1, foo2 : FooEnum2, foo3 : string, foo4 : number, }; I am interested in cre ...

Angular 12 update appears to be causing an issue where CanActivate is not being triggered

After upgrading to angular 12, I am encountering a problem where my application displays a white/blank page upon starting. The issue lies in the fact that the canActivate method within my "RedirectGuard", which implements CanActivate, is no longer being t ...

Concealing a component when the page first loads

Seeking help with the functionality discussed in the thread related to toggling table rows in Angular2: Hide/show a table row when clicking on a link in Angular2 Currently, I have a page displaying multiple products, with an option to select a product fro ...

The error message "Directive does not contain a property called 'element'.ts" is displayed

I'm encountering an issue where the property 'element' is not recognized on 'directive'. I am currently working on implementing functionalities for directives. import { Directive, ElementRef, HostListener } from '@angular/cor ...

Sending information to a RESTapi using Angular 6

Hi there! I am just starting out with Angular 6 and I am encountering an issue while trying to post data to a web API. The error message I am getting is: Error Message: "400 Bad Request: Failed to decode JSON object: Expecting value: line 1 column 1 (char ...

Saving JSON format in VueX State Management

I'm relatively new to using Vue/VueX and I am exploring methods for storing JSON data in the VueX state. Initially, it seemed like a simple task: state { jsonthing: { ... } } However, I encountered an issue where getters return an Observer type ins ...

Issue with Stenciljs custom event not triggering using @Listen decorator

I've been trying to grasp the workings of the custom event emitter. While my mouse events seem to be functioning properly, I'm encountering issues with the custom events. Despite emitting correctly, it appears that the listener is not capturing t ...

Is binding necessary for passing a string to an Angular component?

There are multiple methods for passing string literals to a component: <component inputField="string"></component> <component [inputField]="'string'"></component> <component inputField="{{'string'}}"></ ...