Building a Flexible Component with T Parameter in the Constructor

I'm currently working on creating a versatile component for displaying lists of resources. However, I've encountered an issue when trying to instantiate the component in HTML. I initially tried using this solution to resolve the problem, but it doesn't seem to be effective.

Here is the component code:

<ion-list>
  <ion-item-sliding *ngFor="let entity of entityList" #item>
    <ion-item (click)="navigateToDetail(entity.id)">
      <ion-avatar item-left>
        <img src="http://modexenergy.com/wp-content/themes/modex_wp/img/avatar.png">
      </ion-avatar>
      <h2>{{ entity.email }}</h2>
      <ion-icon name="arrow-forward" item-right></ion-icon>
    </ion-item>
    <ion-item-options side="right">
      <button ion-button color="danger" (click)="delete(entity.id)">
        <ion-icon name="trash"></ion-icon>Delete
      </button>
    </ion-item-options>
  </ion-item-sliding>
</ion-list>

 

export class PageListBaseComponent<T extends IHasId> {

    @Input() entityType: T;
    @Input() detailPageType: any;
    public entityList: T[];

    constructor(public navCtrl: NavController, public navParams: NavParams, public baseProvider: ProviderBase<T>) {

        baseProvider.getList().subscribe(entities => {
            this.entityList = entities;
            console.log(entities);
        });
    }

    delete(id: number) {
        console.log(id);
    }

    navigateToDetail(id: number) {
        console.log('test ' + id)
        this.navCtrl.push(this.detailPageType, { id })
    }
} 

And I call it from my users page like this:

<ion-content padding>
  <page-list-base [entityType]="userType" [detailPageType]="userDetailType">
  </page-list-base>
</ion-content>

export class UsersPage {

  public userType: User;
  public userDetailType: ProfilePage;

  constructor(public navCtrl: NavController, public navParams: NavParams) {
  }
}

This setup fails because the Component references

public baseProvider: ProviderBase<T>
in the constructor, resulting in the Dependency Injector being unable to resolve the type.

I aim to maximize reusability with this generic component. How can I correctly initialize it? If that's not feasible, how can I retrieve the baseProvider after T has been resolved?

Answer №1

My solution involved delaying the initialization process and converting the dependency into an @Input property.

export class PageListBaseComponent<T extends IHasId> {

    @Input() detailPageType: any;
    @Input() set baseProvider(provider: ProviderBase<T>) {
        provider.getList().subscribe(entities =>  {
            this.entityList = entities;
            console.log(entities);
        });
    }

    public entityList: T[];

    constructor(public navCtrl: NavController, public navParams: NavParams) 
    {

    }

    navigateToDetail(id: number) {
        console.log('test ' + id)
        this.navCtrl.push(this.detailPageType, { id })
    }
}

Next, I updated the Page to accept a specific implementation of our dependency.

export class UsersPage {

  public userDetailType: any = ProfilePage;

  constructor(public navCtrl: NavController, public navParams: NavParams, public baseProvider: Users) {
      console.log(this.userType);
  }
} 

Finally, I incorporated the component as follows:

<ion-content padding>
  <page-list-base [detailPageType]="userDetailType" 
      [baseProvider]="baseProvider"></page-list-base>
</ion-content>

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

How to disable the first option in an Angular 2 select dropdown

I'm working with a select component, and here is the code snippet I have: <select name="typeSelection" materialize="material_select" [(ngModel)]="trainingplan.type" > <option [ngValue] = "null" disabled selected>Please choose a ...

Can an Angular Application be created in Azure without using an App Service Plan?

Our client has chosen Azure for their custom app development, utilizing API App for the backend and Angular for the front end. Interestingly, they have opted to not use an App Service Plan for the front end. Can anyone provide insight on how an Angular f ...

Attempting to utilize a namespace-style import for calling or constructing purposes will result in a runtime failure

Using TypeScript 2.7.2 and VSCode version 1.21 with @types/express, I encountered an issue where in certain cases VSCode would report errors like: A namespace-style import cannot be called or constructed, and will cause a failure at runtime. Interestingly ...

What advantages does incorporating observables into Angular 5 HTTP requests offer?

I have been struggling with understanding how to use httpclient in angular 5. As a newcomer to Angular, I am currently following the official angular tutorial but find myself lacking knowledge about observables, promises, pipes, and more. At the moment, I ...

Guide to building a personalized validator for FormGroup

I'm working with a formGroup object that includes 6 fields. Out of these, 5 fields are required together - meaning at least one of them must have a value for the form to be considered valid. The specific field with the value does not matter as long as ...

Issue with Bootstrap 3.3.7 Dropdown: Value not appearing as selected

Recently delving into the world of Bootstrap, I've been using the newest version - Bootstrap 3.3.7. My goal is to show the selected value when a user chooses one of the options. However, with my current code below, the selected value isn't displa ...

Issues arise with rendering nested Angular components for Google Maps

Currently, I am integrating AGM (Angular Google Maps) into my project and aiming to develop a series of custom components that wrap AGM components for enhanced reusability within the application. An issue arises when the markers (in this case) fail to app ...

Strategies for effectively conveying jQuery and Angular

I have integrated jQuery DataTable into my code. I am facing an issue with the dataTables_scrollBody class which requires me to add a custom scroll bar. This is necessary because on Linux, the touch screen functionality in Chrome is not working effectively ...

UI-Router - issue with query parameters preventing arrays with only one item

My application utilizes UI-Router, specifically with a state named Widgets that includes a query parameter accepting an array of widgets: const widgetsState = { name: "widgets", url: "/widgets?{widgets:string[]}", component: Widgets, pa ...

Methods to close the currently active ngx-modal when a new modal is triggered within the same Angular 8 component

I am currently working on developing a versatile modal component that has the ability to be called from within the same modal itself. Is there any way to configure the component and modal in such a manner that when the reusable component is triggered, it ...

Ways to verify the identity of a user using an external authentication service

One of my microservices deals with user login and registration. Upon making a request to localhost:8080 with the body { "username": "test", "password":"test"}, I receive an authentication token like this: { "tok ...

Arranging a Collection of Items into Nested Arrays with Recursive String Paths

I am facing a challenge with organizing a list of items that can have multiple levels of children using an API that provides a path property. The issue arises when the path requires each child to add an incrementing -000n starting from 0001. I am strugglin ...

Having trouble with the ngx-slick-carousel installation

I have been attempting to add the slick-carousel library to my Angular project by following the instructions outlined here: https://www.npmjs.com/package/ngx-slick-carousel. The first two steps, which are: npm install jquery --save npm install slick-caro ...

Ways to incorporate the use of the useAsync hook within a submit function

After importing useAsync(hook from 'react-async') and attempting to utilize it post form submission for a POST request, a "can't use hooks inside functions" error is encountered due to the rules of hooks. How can this issue be resolved in o ...

Is there a way to automate downloading a file in Angular using the browser's built-in download feature?

When I make a request to my webservice to download a zip file, the file content is downloaded secretly and suddenly appears in the download task bar as already fully downloaded (100%). I am using the following method in Angular: const endpoint = "http:// ...

Send properties to the component container

I am currently working on a higher order component that toggles between two children - a component that renders data and a loading component. The challenge I am facing is how to pass the loading state from the data component to the HOC for conditional rend ...

Efficiently storing a newly shuffled list of tasks into the db.json file using Angular

This is the content of my db.json document { "tasks": [ { "id": 1, "text": "Doctors Appointment", "day": "May 5th at 2:30pm", "reminder": true }, { ...

Angular Iterate Array Forms

Is there a way to iterate my rows based on user input? For example, if the user enters 2 values, I need to display 2 rows. How can I achieve this using FormArray? setCount(count:any){ console.log(count); this.count = count; this.countArray = Ar ...

"Enhance your web development with TypeScript and react-select

I find myself in a peculiar predicament. Currently, I am immersing myself in learning TypeScript and here is a brief overview of what transpired so far: const [selectedBankCode , setSelectedBankCode] = useState<string | undefined>(); const [selecte ...

Avoiding non-router links from remaining active while using routerLinkActive in Angular

One component in the list item of the navigation bar caught my attention: <div [routerLink]="link" routerLinkActive="bg-blue-100" class="flex w-[80%] mx-auto p-3 rounded-md font-bold text-xl justify-between items-center gr ...