Invoking a function on an object of a subclass that derives from an abstract class

In the realm of abstract classes, behold this one:

export abstract class BaseStepComponent {
    /** Behold thy base-step ctor */
    constructor() {

    }

    abstract getValue(): string;

}

And lo, here is a component that inherits such abstract glory:

export class SingleChoiceStepComponent extends BaseStepComponent {
    /** Verily, the single-choice-step ctor */
    constructor() {
        super();
    }
    
    @ViewChild("itemList") itemList: ElementRef;

    getValue(): string {
        return this.itemList.nativeElement.value;
    }

}

Yea, many components follow in their footsteps, each with differing logic within getValue()

Elsewhere in my world, I have this member living within a component:

stepItems: QueryList<any>;
@ViewChildren("stepItem") set stepItemsContent(content: QueryList<any>) {
    let items = content.toArray();
    if (items.length > 0) {
        this.stepItems = content;
    }
}

The "Steps" stand tall in a wizard (a form of multiple pages), their types and numbers known not to the application, but all bow to the inheritance of BaseStepComponent

When the time cometh to gather the values returned by getValue(), an obstacle doth abound as mentioned below.

let values: any[] = [];
this.stepItems.forEach(step => {
 let v = step.getValue(); //Behold! An IDE miracle, yet it fails at runtime.
  values.push({ key: step.key, value: v });
});

Alas, due to the highborn nature of BaseStepComponent, a task ariseth unattainable:

let instance = new BaseStepComponent();
instance = Object.assign(instance, step);

Thus do I find myself at an impasse. Might thee possess knowledge on how to transcend this dilemma?

Answer №1

Below is an example of how you can use a base step component along with Angular:

export abstract class BaseStepComponent {
/** Constructor for the base-step */
constructor() {}

abstract getValue(): string;
}

@Component({
 selector: "step1",
 template: `
 <h1>Step 1</h1>
 `,
 providers: [{ provide: BaseStepComponent, useExisting: Step1Component }]
})
export class Step1Component extends BaseStepComponent {
 @Input() name: string;

 getValue(): string {
  return "Step1Component";
 }
}

@Component({
 selector: "step2",
 template: `
 <h1>Step 2</h1>
 `,
 providers: [{ provide: BaseStepComponent, useExisting: Step2Component }]
})
export class Step2Component extends BaseStepComponent {
 @Input() name: string;

 getValue(): string {
  return "Step2Component";
 }
}

To implement this code:

export class AppComponent {
  name = "Angular " + VERSION.major;

  @ViewChildren(BaseStepComponent) items: QueryList<BaseStepComponent>;

  ngAfterViewInit() {
    this.items.map((step: BaseStepComponent) => {
      console.log(step.getValue());
    });
  }
}

You can find a live demo on StackBlitz.

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

Child component received an incorrect input value

Utilizing both the "YearComponent" and "StatPeriod" components has presented some challenges for me. Within my YearComponent, I invoke StatPeriod as follows: <app-save-stat-period [dateBegin]="dateBegin" [dateEnd]="dateEnd" byMonth bestNAverage></ ...

The leaflet popup fails to open for the second time

I used a for loop to create markers on the map. When I click on a marker, a popup opens. However, after clicking on the same marker a second time, the popup does not open. My $scope.resSearchAnnouncement contains JSON data. How can I resolve this issue? ...

Determining interface value based on the presence of another optional interface value

I am working with an interface that looks like this: export interface IButton { label: string; withIcon?: boolean; underlined?: boolean; selected?: boolean; iconName?: string; isLink?: boolean; href?: string; onCLick?: () => void; } My question ...

Modifying the editable functionality of grouped rows in Angular-Slickgrid

Looking for help with angular-slickgrid implementation. I need to enable editing of grouped rows (using Formatter: sum for children rows) and pass the values to all children within the same group. How can this be done without changing the references? ...

Using debounceTime and distinctUntilChanged in Angular 6 for efficient data handling

I recently came across a tutorial on RxJS that demonstrated the use of debounce and distinctUntilChanged. I'm trying to implement it in Angular 6, but I'm facing some challenges. Here is the code from the tutorial: var observable = Rx.Observabl ...

Which is the best option: Service variable, Service Observable, or Service Subject?

Lately, I've been contemplating the idea of global variable declaration, and I'm struggling to see the advantage of using a Subject in a service instead of a simple variable or even an Observable. Could you help me understand why someone would ch ...

Retrieve the array from the response instead of the object

I need to retrieve specific items from my database and then display them in a table. Below is the SQL query I am using: public async getAliasesListByDomain(req: Request, res: Response): Promise<void> { const { domain } = req.params; const a ...

Creating a unique custom view in React Big Calendar with TypeScript

I'm struggling to create a custom view with the React Big Calendar library. Each time I try to incorporate a calendar component like Timegrid into my custom Week component, I run into an error that says react_devtools_backend.js:2560 Warning: React.cr ...

What is the reason behind Typescript executing the abstract class before anything else?

I'm currently facing a challenge solving an abstract class problem with Typescript. Let me explain what I am trying to accomplish. There is a class named Sword that extends Weapon. Each Weapon must have certain properties like the damage, but since e ...

Creating an Http interceptor in Ionic 3 and Angular 4 to display a loading indicator for every API request

One of my current challenges involves creating a custom HTTP interceptor to manage loading and other additional functions efficiently. Manually handling loading for each request has led to a considerable increase in code. The issue at hand: The loader is ...

Steer clear of chaining multiple subscriptions in RXJS to improve code

I have some code that I am trying to optimize: someService.subscribeToChanges().subscribe(value => { const newValue = someArray.find(val => val.id === value.id) if (newValue) { if (value.status === 'someStatus') { ...

Discover the potential of JavaScript's match object and unleash its power through

In the given data source, there is a key called 'isEdit' which has a boolean value. The column value in the data source matches the keys in the tempValues. After comparison, we check if the value of 'isEdit' from the data source is true ...

Warning: An alert has been triggered while generating files using create-react-app

npm WARN <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e896999d9c81849ba8dbccd1ded8d4cfdcd0c59bc6cbca">[email protected]</a> requires a peer of typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= ...

Sharing information between components in Angular 2 that are not directly related as parent-child relationships

Hey there, I'm just getting started with Angular 2 and ran into a bit of a roadblock. In my homepage component, I have a ul element where I display job descriptions fetched from a Firebase API call. The data is stored in an array called "jobs" and dis ...

Ensuring strictNullChecks in Typescript is crucial when passing values between functions

When using the --strictNullChecks flag in TypeScript, there seems to be an issue with inferring that an optional property is not undefined when the check occurs in a separate function. (Please refer to the example provided, as articulating this clearly is ...

Building basic objects in TypeScript

My current project involves utilizing an interface for vehicles. export interface Vehicle { IdNumber: number; isNew: boolean; contact: { firstName: string; lastName: string; cellPhoneNumber: number; ...

What is the process for updating the authService in Angular to return an observable using the map function from the previous version?

I recently followed a tutorial on JWT authentication with ASP.NET Core 2 Web API, Angular 5, .NET Core Identity, and Facebook login. The tutorial can be found here. While the tutorial was well-written, it utilized an older version of Angular (I am using An ...

In order to incorporate Bootstrap with Angular2, I had to execute a specific command

For incorporating bootstrap with angular2, I executed the following command: $ npm install --save @ng-bootstrap/ng-bootstrap The output displayed: <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="40212e27352c2132726d313529232 ...

A guide to accessing parent attributes in Vue3 using typescript

Within my child component, I am facing an issue where I need to access the parent object but the commented lines are not functioning as expected. The structure of AccordionState is defined below: export type AccordionKeys = | "open" | "disa ...

Error message: "Unable to find a windows instance" encountered while conducting tests on Paho MQTT Client using mocha and typescript

After spending countless days searching online, I have yet to find any resources on testing the Paho MQTT Client. My approach so far has been somewhat naive, as shown below: import { suite, test, slow, timeout, skip, only } from 'mocha-typescript&apo ...