Utilizing Dependency Injection with TypeScript and Angular 5 in an Abstract Class

In my BaseComponent, I have some dependencies injected. The first dependency, EntityService, is essential and correctly implemented.

However, the AnyOtherService is only utilized within the abstract BaseComponent. Instead of injecting it into the ChildComponent where it remains unused, I prefer to have it injected solely into the BaseComponent.

Why must it pass through the ChildComponent before reaching the BaseComponent? A better approach would be to keep it encapsulated within the BaseComponent.

base.component.ts

export abstract class BaseComponent {
  constructor(
    protected entityService: EntityService,
    // protected anyOtherService: AnyOtherService // @todo add this
  ) {
  }
}

child.component.ts

@Component()
export class ChildComponent extends BaseComponent {

  constructor(
    private firstService: FirstService,
    private secondService: SecondService,
    protected anyOtherService: AnyOtherService // @todo remove this
  ) {
    super(
      firstService,
      anyOtherService // @todo remove this
    ); 
  }
}

Answer №1

To easily pass the Injector to the constructor of a base component, you can do the following (UPDATE):

export abstract class BaseComponent {
  protected anyOtherService: AnyOtherService;

  constructor(
    inject: Injector
    protected entityService: EntityService,
    // protected anyOtherService: AnyOtherService // @todo add this
  ) { 
     this.anyOtherService= inject.get(AnyOtherService);
  }
}


@Component()
export class ChildComponent extends BaseComponent {

  constructor(
    inject: Injector,
    private firstService: FirstService,
    private secondService: SecondService       
  ) {
    super(
     inject,
     firstService
    );       
  }
}

The concept here is to provide the Injector and certain providers in the child component, then pass them to the parent base component without having to include all dependencies of the base class. By passing the injector, child components don't have to inject all dependencies of the parent class and explicitly pass them through the constructor like dep1, dep2, and so on.

Could you elaborate on why it is necessary for properties inside the child component to be defined as private, while those in the parent component are defined as protected?

I believe that the injector should not be declared as a property of either the child or base class. If it were to be declared, an error related to both classes having the same property would arise as mentioned in your comment. This issue arises because both the Base and Child classes cannot have identical properties in their respective scopes. Hence, by not defining an access modifier (private/protected) for the injector in the constructor, we are able to address this limitation and ensure that the Injector is only utilized within the constructor for manual injections required in specific scenarios like this one.

Answer №2

If you're looking for a way to utilize an injector in Angular, consider exporting it from appModule and using it in your base class like this:

import {Injector} from '@angular/core';

//exporting injector 
export let AppInjector: Injector;

export class AppModule {
  constructor(private injector: Injector) {
    AppInjector = this.injector;
  }
}

Then in your base component file (base.component.ts), you can access any service by utilizing the exported injector:

export abstract class BaseComponent {
  private anyOtherService : AnyOtherService ;
  constructor(
    protected entityService: EntityService,
    // protected anyOtherService: AnyOtherService // @todo add this
  ) {
    this.anyOtherService = AppInjector.get(AnyOtherService );
  }
}

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

Can one utilize Javascript/Angular to listen for a 'request sent' event trigger?

Is there a method in a Javascript/Angular application to intercept a 'request-sent' event triggered by the browser right after the request is sent out? Our goal is to manage and prioritize the order of outgoing requests, potentially sending each ...

Error: The specified property is not found in type 'never' - occurring with the ngFor loop variable

When working with API responses and dynamically sorting my view, I utilize an ngFor loop. Here's the snippet of code in question: <agm-marker *ngFor="let httpResponses of response" [latitude]= "httpResponses.lat" [longitude]=& ...

Guide on conducting unit tests for the provided code in Angular 8

I am currently working on implementing unit testing for this specific code snippet. applyFilter(filterValue: string) { this.dataSource.filter = filterValue.trim().toLowerCase(); this.DMDataSource.filter = filterValue.trim().toLowerCase(); // con ...

Tips for maintaining consistent column size in an angular material table as the screen size shrinks

I have a material table with 9 columns and I want to keep the column size consistent even when the screen size is reduced. Currently, as I decrease the screen size, the last column shrinks first while the other columns remain the same size, creating an un ...

Unexpected disappearance of form control in reactive form when using a filter pipe

Here is a reactive form with an array of checkboxes used as a filter. An error occurs on page render. Cannot find control with path: 'accountsArray -> 555' The filter works well, but the error appears when removing any character from the fi ...

What's the best way to format text as bold in a .ts file so that it appears as [innerText] in the HTML section?

When looking to emphasize specific text without using [innerHTML], what is the alternative method besides the usual line break changes in the interface? How can we make certain text bold? For instance: .ts file string = This is a STRING bold testing.&bso ...

A step-by-step guide on utilizing SCURI to automatically generate unit test cases in Angular 8 and beyond

Have you heard about the npm package SCURI? It's a handy tool for automatically writing unit test cases for .ts files to achieve over 70% coverage. All you have to do is install this package and then create an autoSpy.ts file to specify how to mock o ...

Bringing a JavaScript function into a TypeScript file results in it being treated as a namespace

Trying to bring a vanilla JavaScript function into a TypeScript file within a React Native app has presented some challenges. The import process goes smoothly when working with JS, but switching to TS triggers the error message: Cannot use namespace &apos ...

Creating an external stylesheet and including it in a component: A beginner's guide

Hello, I am looking to create an external CSS file and link it to a component. I have provided the code below, but I am encountering errors which are mentioned further down. Please review the code and let me know where I may have made a mistake and provide ...

The elusive 'module' cannot be located when working with commonjs

I am currently working on the following code snippet... @Component({ module: module.id, selector: 'hero', templateUrl:'hero.component.html', styleUrls: ['hero.component.css'], directives ...

Show data stored in a MongoDB collection as an HTML table by utilizing Angular CLI as the frontend interface

Hey there, I am currently diving into the world of nodejs, mongodb, and angular cli. As part of my college project, I'm facing some challenges. Specifically, I need to showcase the array data from mongodb on an existing table within the angular compon ...

How to dynamically assign a value in a React datepicker component in a React application

Having troubles with react-datepicker? I encountered an issue where setting the value of react-datepicker from props caused it to either not show the value or display a 'wrong time format' error. Here is a snippet of the Datepicker code: this.sta ...

Distribute a TypeScript Project on NPM without exposing the source code

Issue: My library consists of numerous .ts files organized in structured folders. As I prepare to publish this library, I wish to withhold the source (typescript) files. Process: Executing the tsc command results in the creation of a corresponding .js fil ...

Demonstration of basic geometric shapes being generated using Forge Viewer Angular

Using the ng2-adsk-forge-viewer library in Angular 7, I am attempting to render a .dmg file within the browser and create a custom geometry on the view. After creating an Extension and adding the addToScene method, while the Extension runs successfully, I ...

Evaluating h1 content in HTML using Angular Protactor testing

I am completely new to end-to-end testing. I have a login page in my application that should be displayed to users when they log out. However, I am facing an issue with retrieving the text from a specific div element containing an h1 tag, leading to unexpe ...

Transforming the string attribute of an object within a JavaScript array through mapping

Here is an array of objects: { "attr1": 123, "attr2": "a.end", }, { "attr1": 123, "attr2": "b.start", } The task is to remove the first part of the attr2 string up to and including the '.& ...

Empty spaces are mandatory here

When experimenting with declaring a function that must be called with a specific context (undefined, null, or global), I made an interesting discovery. I noticed that when declaring a function with this: void, it can be called with any context. However, if ...

Having difficulty removing new or existing lines on StackBlitz

I attempted to experiment with React on StackBlitz, but I encountered a problem where I couldn't delete any lines of code. It seems that while I can add new lines of code, deleting them is not an option. Even when logging in with GitHub, the issue per ...

The AppModule's CanLoad protector

I recently developed an Angular application using angular-cli and successfully implemented CanLoad guard for my modules. The CanLoad check verifies if the user is logged in before loading a module. My question is, can I apply CanLoad guard to AppModule as ...

What could be the reason behind my Vue file triggering a TS6504 error and suggesting to "allowJs"?

My Vue 3 project, which incorporates TypeScript, is encountering an issue when I attempt to execute vue-tsc --noEmit. error TS6504: File '/proj/src/pages/Index.vue.__VLS_template.jsx' is a JavaScript file. Did you mean to enable the 'allowJs ...