How can we avoid duplicating injectors in a child class when extending a class that already has injected services?

Delving deep into TypeScript inheritance, particularly in Angular 11, I've created a BasePageComponent to encompass all the necessary functions and services shared across pages. However, I've encountered an issue where my base class is becoming bloated because it includes services that are only used on one or two pages.

export class BasePageComponent {

  constructor(
    public uiPopupService: UiPopUpService,
    public loaderService: LoaderService,
    public questionService: QuestionService,
    public aBunchOfOthers: OTHERS,
    public exampleOneOffService: ExampleOneOffService
  ) {}
}

Realizing the inefficiency of this approach, I thought about passing only the necessary services up to the BasePageComponent by duplicating them in each child component:

export class ChildPageComponent extends BasePageComponent {

  constructor(
    public uiPopupService: UiPopUpService,
    public loaderService: LoaderService,
    public questionService: QuestionService,
    public aBunchOfOthers: OTHERS,
    private exampleOneOffService: ExampleOneOffService
  ) {
    super(uiPopupService, loaderService, questionService, aBunchOfOthers);
  }
}

While I can follow the above method, considering I have around 15-20 micro services included in the base class, I'm looking for a way to declare just the additional service in the child class while inheriting the rest from the parent. Is there a way to achieve this?

export class ChildPageComponent extends BasePageComponent {

  constructor(private otherExampleService: OtherExampleService){
    super() 
  };
}

Is there a known pattern for this requirement that I might be overlooking in my research?

Answer №1

Answer №2

Special thanks to @MikeOne's suggestion for directing me to another helpful answer ( Inject a service manually ).

I managed to utilize Injector.get for the 15 smaller services that are utilized in almost every child component. For the larger services and those only utilized in a few child components, I injected them directly into the appropriate components.

For anyone else visiting this in the future: A snag I encountered was Angular's ActivatedRoute not functioning with Injector.get (refer to How to retrieve a route param using Injector.get(ActivatedRoute)?). Therefore, I needed to inject it into each relevant component, which fortunately covered the majority of them. Despite this, it is still preferable to have fewer than 16 individual services initialized on every page.

Answer №3

The function of the DI is not as straightforward.

When using DI, only the constructor parameters are accessible, without any knowledge of the parent class.

If a subclass calls the DI, the parent classes won't receive anything from it. Instead, the parameters need to be passed through super()

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

The Angular Material dialog fails to display content when triggered within an event listener in Google Maps

Within my project, I am utilizing Angular 6.0.6 and Angular Material 6.3.0. One issue I have encountered is with a dialog component that I have added to the entryComponents in the app module. Strangely, when I attempt to open this dialog within the rightcl ...

Merge arrays values with Object.assign function

I have a function that returns an object where the keys are strings and the values are arrays of strings: {"myType1": ["123"]} What I want to do is merge all the results it's returning. For example, if I have: {"myType1": ["123"]} {"myType2": ["45 ...

Scroll automatically to the last div whenever a button is clicked using React and Typescript

I'm currently working on an application being developed in React + Typescript. I am trying to implement auto-scroll functionality to the last div within a parent div where child divs are dynamically added based on data from an array of objects. The da ...

The submission functionality of an Angular form can be triggered by a separate button

I am currently developing a Material App using Angular 12. The Form structure I have implemented is as follows: <form [formGroup]="form" class="normal-form" (ngSubmit)="onSubmit()"> <mat-grid-list cols="2" ...

Angular select element is not functioning properly with the `addEventListener` method

My current project involves creating a table using the primeng library. The table consists of three rows and three columns, and all the data is static. Even though I am utilizing an external library, I find myself traversing the DOM directly. <p-table ...

Issue encountered while executing ./node_modules/.bin/cucumber-js within GitLab CI

I've encountered an issue while setting up a continuous integration build for my node project. Despite the fact that npm run test runs smoothly in my local setup, I am facing an exception in GitLab CI. The error arises from the following test command ...

io-ts: Defining mandatory and optional keys within an object using a literal union

I am currently in the process of defining a new codec using io-ts. Once completed, I want the structure to resemble the following: type General = unknown; type SupportedEnv = 'required' | 'optional' type Supported = { required: Gene ...

Incorporating TypeScript into a project that already contains .js files

I currently have a NodeJS project with .js files written in ES6. I am interested in integrating typescript into this existing project. What steps should I follow? Can I simply introduce .ts files within the same directory structure? One issue I have encou ...

Error: Unable to access the 'visitStatement' property of an undefined object within Angular 2

Help! I encountered an error in my angular2 application. The error message says: TypeError: Cannot read property ‘visitStatement’ of undefined ...

Is there a way to determine the most recent Typescript target compatibility for every Node version?

When using any version of Node, how can I identify the appropriate Typescript Compiler Option for target that offers the most functionality? I want to eliminate any guesswork. Specify the ECMAScript target version as: "ES3" (default), "ES5", "ES6"/"ES20 ...

Testing a subclass in Angular 6 using Karma and the @Input decorator

After finding no answers to related questions, I've decided to pose my own specific case regarding unit testing an Angular 6 component that is a subclass of a base component. The base component itself includes an @Input decorator and looks like this: ...

Tips for preventing repetition of code in multiple entry points in Rollup

My goal is to use rollup to process a group of input files and generate multiple output files in the dist directory that all have some common code shared between them. Below is my current rollup configuration: import path from 'path'; import pat ...

Is it possible for a lambda in TypeScript to have access to the class scope but return undefined

In my TypeScript code, I have a class used as a Pipe in Angular 2 to render markdown. It compiles successfully but encounters a runtime exception on a specific line: var Remarkable = require('remarkable'); @Pipe({ name: 'markdown' ...

Removing a field from a collection using firebase-admin: Tips and tricks

I currently have a collection stored in Firebase Realtime Database structured like this: https://i.sstatic.net/jNiaO.png My requirement is to remove the first element (the one ending with Wt6J) from the database using firebase-admin. Below is the code s ...

Attempting to add a new property to every object in an array using TypeScript

In my Angular project, I have a specific code block that retrieves an array of objects containing contact records. Within a 'forEach' loop, I am generating a new field for each contact record to store the user's initials. The goal is to ad ...

How can I conceal an element upon page load using Ionic framework?

index.component.ts initialize() { // Execute necessary functions after loading this.index.ready().then(() => { if(this.index.is('core')){ // this.menu.enable(false, 'mobileOnlyPages'); }else{ ...

Customizing output paths for script files in angular.json with Angular

Is there a way to set up the configuration in angular.json so that script files are output as shown in the directory tree below? Note: The file aaa.js has been renamed from main.js /assets/js/aaa.js ...

Steer clear of receiving null values from asynchronous requests running in the background

When a user logs in, I have a request that retrieves a large dataset which takes around 15 seconds to return. My goal is to make this request upon login so that when the user navigates to the page where this data is loaded, they can either see it instantly ...

Retrieving template variable within a directive's host listener function

Can 'habitCellInfo' be accessed from the template within the onvalueChanged host listener? <div *dxTemplate="let habitCellInfo of 'habitEditCellTemplate'"> <dx-select-box (onValueChanged)=" onHabitEdi ...

"Enhance your user experience with seamless drag and drop functionality for transferring items between

I am currently working on transferring items between a list and table using the drag-and-drop feature of PrimeNG. Both elements should be able to act as both drag sources and drop destinations. My project is based on PrimeNG-9.0.0 and Angular 9.0.2 https ...