Utilizing Angular Dependency Injection for Extending Base Services with Subclasses

My service setup includes a base service and two services that inherit from it:

@Injectable({ providedIn: 'root' })
export class BaseService {
  foo(src?: string){
    return `speaking from ${src || 'BaseService'}`;
  }
}


@Injectable({ providedIn: 'root' })
export class SomeService extends BaseService {
  foo(){
    return super.foo('SomeService')
  }
}

@Injectable({ providedIn: 'root' })
export class AnotherService extends BaseService {
  foo(){
    return super.foo('AnotherService')
  }
}

I want to inject these services into a component and get instances of all three classes:

@Component({
    selector: 'my-app',
    template: `
        <div>
            <p>Who's there?</p>
            <p>{{ base }}</p>
            <p>{{ some }}</p>
            <p>{{ another }}</p>

        </div>
    `,
})
export class App {
    base: string;
    some: string;
    another: string;

    constructor(base: BaseService, some: SomeService, another: AnotherService) {
        this.base = base.foo();
        this.some = some.foo();
        this.another = another.foo();

    }
}

Instead, I am getting three instances of the same class (HTML output):

Who's there?

speaking from BaseService

speaking from BaseService

speaking from BaseService
  • Why is this happening?
  • Why are SomeService, AnotherService and BaseService not considered unique tokens for Angular Dependency Injection?

It appears that adding

...    
{ provide: SomeService , useClass: SomeService },
{ provide: AnotherService , useClass: AnotherService },
...

in the providers will resolve the issue.

  • Why is this explicit declaration necessary?

A plnkr demonstrating the issue:

Answer №1

SomeService and AnotherService inherit the decorator metadata from BaseService, causing angular to inject an instance of BaseService in place of them.

This setup can be risky, as invoking any instance member in either SomeService or AnotherService that is not inherited from BaseService may result in a runtime error.

To achieve the desired behavior, a more secure method would be to inherit from a shared abstract base class without any decorators:

export abstract class AbstractBaseService {
  foo(src?: string) {
    return `communicating from ${src || 'AbstractBaseService'}`;
  }
}

@Injectable({ providedIn: 'root' })
export class BaseService extends AbstractBaseService {
  foo() {
    return super.foo('BaseService');
  }
}

@Injectable({ providedIn: 'root'})
export class SomeService extends AbstractBaseService {
  foo() {
    return super.foo('SomeService');
  }
}

@Injectable({ providedIn: 'root' })
export class AnotherService extends AbstractBaseService {
  foo() {
    return super.foo('AnotherService');
  }
}

I made changes to your plnkr to demonstrate this approach.

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

Utilizing Shopify API to seamlessly add items to cart without any redirection for a smoother shopping experience

Looking for a solution to submit an add to cart POST request without any redirection at all? I have tried changing return_to to "back" but that still reloads the page, which is not ideal. My goal is to smoothly add the item to the cart and notify the cli ...

Adding incremental values to a variable using JavaScript within the framework of jQuery and AJAX

In my JavaScript code that utilizes jQuery and AJAX, I have created a dynamic array containing multiple values for AJAX requests. The array is structured as follows: <script type="text/javascript> var array = Array("y", "y", "x", "y", "y", "y"); fu ...

Determine changes in data retrieved from a JSON file using React

I've been working on a cryptocurrency app using React and a JSON API to fetch the latest data. My approach involves using fetch to load the JSON API and setInterval to refresh the app every 10 seconds. Now, I'm wondering if there's a way to ...

Can you explain the distinction between an optional field and a union?

Is there a significant distinction between the following structures: { ok: boolean; } | { ok: boolean; error: any; } and: { ok: boolean; error?: any; } I have observed variance in the inferred types of frontend methods' return ou ...

Unusual "visual" phenomenon with autocomplete feature in VUE.js

Can someone review this code snippet? Check out the code here This is a peculiar example of a custom autocomplete VUE component. If you enter a value in one of the fields in Section 1 (like 'Apple'), then click on the Next button, you'll ...

Issue with React-select: custom Control prevents select components from rendering

Implementing react-select@next and referring to the guide here for custom Control components is not yielding the desired outcome. import TextField from "@material-ui/core/TextField"; import Select from "react-select"; const InputComponent = (props) => ...

Slider handle for Material UI in React component reaches the range value

In my application, I am using a range slider component from material-UI. The main page displays a data table with the fields: id, name, current price, new price. The current price for each item is fixed, but the new price will be determined based on the s ...

The error being thrown is related to Next.js 13 cache setting of 'no-store'

Check out this snippet of code async function fetchData() { const response = await fetch('http://127.0.0.1:1337/api/posts', { method: 'GET', headers: { 'Content-Type': 'application/json', Author ...

False return - Inoperative link - Scroll option

I have a JavaScript drop-down menu that is functioning correctly, but when I click on one of the links in the dropdown, the link does not work. I suspect it has something to do with my "return false/true" setup. Here's my JavaScript code: function d ...

Having trouble retrieving all JSON properties

I am facing an issue with my json structure where I am unable to access certain properties. I can only access the main properties like type, properties, and so on within that hierarchy level. However, I cannot seem to access icon, iconURL, or title. The da ...

Typescript: Assigning Variables Without Prior Declaration

In my upcoming Node.js application, I decided to use TypeScript for development. However, I encountered a perplexing issue while working on the code below: class AuthService { public async init(req: Request, res: Response) { let user: IUser | ...

Preventing over-purchasing products by managing Knex.js inventory levels

Currently, I am in the process of developing an online store for my school's guild organization. I must admit that I lack experience working with databases and Knex.js is still a bit challenging for me. An issue arises when multiple users simultaneo ...

Utilize filtering techniques on a nested system

After creating an Angular app to display a hierarchy, I am now attempting to add a text box on top of the hierarchy for data filtering purposes. Despite trying various filter examples, I have not achieved much success. My goal is to implement Angular bind ...

What is the most strategic way to conceal this overlay element?

Currently, the website I'm developing features a series of navigation elements at the top such as "Products" and "Company." Upon hovering over the Products link, an overlay displays a list of products with clickable links. Positioned at the top of the ...

The JavascriptExecutor is unable to access the 'removeAttribute' property of a null object

While utilizing Javascript executor to remove the readonly attribute, I encountered an error message: Cannot read property 'removeAttribute' of null. I came across various discussions where users suggested that removing AdBlock from Chrome solve ...

Trie-based autocomplete functionality

I am currently creating an auto-completion script and I'm considering utilizing a trie data structure. My main concern is that I want all possible matches to be returned. For instance, when I type in the letter r, I expect to see all entries beginning ...

Incorporating Earth Engine scripts into my AngularJS project to showcase NDVI data layer on a Google Map

Is there anyone who has successfully integrated the Earth Engine API into their front-end JavaScript code? I've been attempting to follow the demo on the earth-engine repository to add a layer to a map, but I haven't had any success. It seems lik ...

React 16 is able to efficiently render an array of numbers into table data using the map function

In my quest to display the most frequently used words, I have successfully fetched data from an API. I have set up the state for words and mapped the array in render(). However, instead of displaying the words along with their counts, I only see numbers ...

Searching for data based on specific keywords in Angular 2, rather than using a wildcard search, can be done by utilizing the key-in

My dropdown contains 100 values, and I am currently able to search for these values based on key input using wild search. However, I would like the dropdown to display values based on the specific alphabet that I enter first. HTML: <div class="col- ...

Clear the data once the checkbox has been unchecked

Within my div containers, each containing a result, there is a checkbox associated with each one. When a user clicks on a single checkbox, the value of the currently checked box is sent to another page via an ajax call. The data is then fetched and display ...