Creating a versatile Angular component with personalized settings without relying on the @Input directive

Hello fellow members of the Angular community,

I am seeking advice on how to create a generic icon component that avoids code duplication.

custom-icon-component:

@Component({
  selector: 'app-custom-icon',
  template: `
    <style>
      button {
        background-color: Transparent;
        border: none;
        cursor: pointer;
        overflow: hidden;
        outline: none;
      }

      mat-icon {
        font-size: 18px;
      }
    </style>
    <button (click)="onClickCustomIcon($event)">
      <mat-icon
        matTooltip="Select action"
        matTooltipPosition="below"
        class="material-icons-outlined"
        >{{ iconRegistry.CUSTOM }}</mat-icon
      >
    </button>
  `,
  styles: [],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class CustomIconComponent implements ICellRendererAngularComp {
  params;
  disabled = false;
  iconRegistry = IconRegistry;

  agInit(params): void {
    this.refresh(params);
  }

  refresh(params): boolean {
    this.params = params;
    return true;
  }

  onClickCustomIcon($event): void {
    const params = {
      rowData: this.params.data,
      rowIndex: this.params.rowIndex
    };
    this.params.onClick(params);
  }

update-icon-component:

import { ChangeDetectionStrategy, Component } from '@angular/core';
import { ICellRendererAngularComp } from 'ag-grid-angular';
import { IconRegistry } from '../../../icon-registry/icon-registry';

@Component({
  selector: 'app-update-icon-render',
  template: `
    <style>
      button {
        background-color: Transparent;
        border: none;
        cursor: pointer;
        overflow: hidden;
        outline: none;
      }
      button :hover {
        background-color: #efeadf;
      }
      mat-icon {
        font-size: 18px;
      }
    </style>
    <button
      *ngIf="params?.data && !!params.data.objectId && !!params.data.objectPath"
      (click)="onUpdateClick($event)"
      [disabled]="params?.disabledGetter ? params.disabledGetter(params) : false"
      data-cy="icon-cell-Update"
    >
      <mat-icon [matTooltip]="tooltip" matTooltipPosition="below" class="material-icons-outlined">
        {{ iconRegistry.PENCIL }}
      </mat-icon>
    </button>
  `,
  styles: [],
  changeDetection: ChangeDetectionStrategy.OnPush
})

export class UpdateIconRenderComponent implements ICellRendererAngularComp {
  params;
  iconRegistry = IconRegistry;
  tooltip: string;

  agInit(params): void {
    this.params = params;
    if (this.params?.tooltipGetter) {
      this.tooltip = this.params.tooltipGetter(this.params);
    } else {
      this.tooltip = this.params?.tooltip;
    }
  }

  onUpdateClick($event): void {
    $event.stopPropagation();
    const params = {
      rowData: this.params.node.data
    };
    this.params.onClick(params);
  }

  refresh(params): boolean {
    this.params = params;
    return true;
  }

The only variations are the ICON and logic within the agInit function.

I cannot utilize the @Input feature since these components will be used within TypeScript code rather than HTML as shown below:

  this.frameworkComponents = {
      customButtonRenderer: CustomIconComponent
    };

Any suggestions on creating a single generic component that can accommodate any icon?

Answer №1

To implement a more abstract approach, one could consider creating a RowIconComponent as the base class to extend from. Here is an example of how this might look:

export abstract class IconComponent {
  params;
  iconRegistry = IconRegistry;
  tooltip: string;

  refresh(params): boolean {
    this.params = params;
    return true;
  }

  abstract onClick($event): void;
  abstract agInit(params): void;
}

Here's an updated version:

@Component({
  // ...
})
export class DeleteRowIconComponent extends IconComponent implements ICellRendererAngularComp {
  agInit(params): void {
    this.refresh(params);
  }

  onClick($event): void {
    const params = {
      rowData: this.params.data,
      rowIndex: this.params.rowIndex
    };
    this.params.onClick(params);
  }
}

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

What is the method of duplicating an array using the array.push() function while ensuring no duplicate key values are

In the process of developing a food cart feature, I encountered an issue with my Array type cart and object products. Whenever I add a new product with a different value for a similar key, it ends up overwriting the existing values for all products in the ...

Plunkr Experimentation: Issues with Angular 2 Final Plunk Deployment

Can anyone explain why the Angular 2 Final Test Plunk I am using (https://plnkr.co/edit/JY0hcFdaziIsFFJmRaz3?p=preview) is not functioning properly? The console shows this error message: 'Refused to display 'https://run.plnkr.co/QdUdeWWKa25MFN9 ...

Beginning external plugin in Angular 4 application

Is it possible to incorporate an external plugin into an Angular 4 application? I am looking to utilize the niceScroll plugin for a scrollable div, which is defined within a component. <div class="d-flex" id="scrollable"> <app-threads-list> ...

When accessing APIs, create an array of observables for each user call and then trigger a function once all are successfully resolved

As I aim to generate a list of observables while a user engages with the webpage, I am faced with the challenge of individually subscribing to each observable, but desiring another function to execute after individual or multiple simultaneous API calls are ...

The Angular2 Observable fails to be activated by the async pipe

Take a look at this simple code snippet using angular2/rxjs/typescript public rooms: Observable<Room[]>; constructor ( ... ) { this.rooms = this.inspectShipSubject .do(() => console.log('foo')) .switchMap(shi ...

Issue encountered while authenticating client secret from backend for newly created Stripe subscription

There seems to be an issue with confirming the client secret sent from the express backend to the frontend, specifically in a React Native-based mobile application. The clientSecret is being sent in the same manner as described above. On the frontend Rea ...

Having trouble with JSON parsing in Promise execution

I am in the process of developing a Promise with the objective of adding up any numbers discovered within an array or JSON object. The add() function is designed to receive a series of URLs as a string input and calculate the total sum of those URLs. Her ...

Angular: Issue with setting a new value in child component on the second attempt via @Input directive

Implementing a child component to manage a dropdown feature. The parent component includes a reset button to revert the user's selection in the dropdown (child component) back to 'None'. Check out the code link here. app.component.html: ...

Retrieving the inner text of a dragged element using Angular Material's DragAndDrop feature

Can the inner text of a dragged element be retrieved and utilized in the "onDrop" function within Angular's cdkDragAndDrop feature? onDrop(event: CdkDragDrop<string[]>) { if (event.previousContainer === event.container) { moveItemIn ...

Creating OpenAPI/Swagger documentation from TypeScript code

I am in search of a solution to automatically create OpenAPI/Swagger API definitions based on my Node.JS/Express.JS/Typescript code. It would be perfect if I could simply add annotations to my Express Typescript base controllers and have the OpenAPI/Swagg ...

Error when attempting to add data into MongoDB using Node.JS: "The type 'string' cannot be assigned to type 'ObjectId | undefined'."

Attempting to add a document to the collection results in an error when specifying the _id field of the added document. How can I insert a document with an _id that is not an ObjectId? The error occurs with the following code. Omitting the _id resolves th ...

A step-by-step guide on deploying an application using ASP.NET Core and Angular within Visual Studio

I recently completed a tutorial on integrating ASP.NET Core with Angular, which you can find at this link. After following the tutorial, I successfully set up a solution that includes both a backend ASP.NET Core and an angular client application. However ...

Issues arising from an aging Angular project

I'm currently facing an issue with installing node and typescript for an older angular project that I have inherited. This project is using angular 2.4.10 After downloading and installing node version 6.9.5 from the executable file, I proceeded to in ...

Next.js routing can sometimes be unpredictable, especially when navigating from a nested route

I recently set up a directory named dashboard within the pages folder, and it contains the following files: index.tsx customers.tsx invoice.tsx items.tsx When a user navigates to http://localhost:3000/dashboard, the index.tsx page is displayed. However, ...

Transforming Javascript into Typescript with node modules in Visual Studio 2015

After developing a JavaScript web app using npm and webpack, I successfully converted all the .js files to .ts using the PowerShell command found here. Now, I am looking to transition to a VS2015 TypeScript project but struggling to find guidance on how ...

Error: ngModel does not reflect dynamic changes in value

After calling a Spring service, I am receiving JSON data which is stored in the "etapaData" variable. 0: id: 266 aplicacao: {id: 192, nome: "Sistema de Cadastro", checked: false} erro: {id: 220, nome: "Falta de orçamento", checked: false} perfil: {id: 8, ...

How to selectively make properties optional in Typescript conditions

Currently, I am working on creating a utility type to unwrap nested monads of Options in my code. Here is the progress I have made so far: export interface Option<T> { type: symbol; isSome(): boolean; isNone(): boolean; match<U>(fn: Mat ...

Guide to transitioning from Angular 4 to Angular 7: incorporating 'URLSearchParams' and 'RequestOptions'

I am in the process of updating my project from Angular 4 to Angular 7. I have successfully switched from using http to httpClient and changed to common/http as well. However, I am inexperienced with Angular and unsure how to convert urlSearchParams and ...

Changing JSON into an array with typescript

I have encountered a JSON structure that is causing me some trouble: const help = [ { "en": [ { "test2": [ { "title": "Naslov1", &quo ...

Unable to execute dockerfile on local machine

I'm currently attempting to run a Dockerfile locally for a Node TypeScript project. Dockerfile FROM node:20-alpine EXPOSE 5000 MAINTAINER Some Dev RUN mkdir /app WORKDIR /app COPY ./backend/* /app RUN npm i CMD ["npm","start"] However, I encoun ...