Supply additional parameters to the method decorator within an Angular component

Imagine a scenario where there are multiple methods requiring the addition of a confirmation dialog. In order to streamline this process, a custom decorator is created.

@Component({...})
export class HeroComponent {
  constructor(private dialog: MatDialog) {}

  @confirmByDialog(this.dialog)
  deleteHero() { ... }
}

export function confirmByDialog (dialog: MatDialog): MethodDecorator {
  return (target: Function, key: string, descriptor: any) => {
    const originalMethod = descriptor.value;

    descriptor.value = (...args: any[]) => {
      const dialogRef = dialog.open(ConfirmationDialogComponent);
      return dialogRef
        .afterClosed()
        .subscribe((confirmed: boolean) => {
          if (confirmed) {
            originalMethod();
          }
        });
    };

    return descriptor;
  };
}

However, an issue arises with the code:

Cannot read property 'dialog' of undefined (hero.component.ts)

The question now stands: How can additional parameters be passed to a decorator? One potential solution could involve passing the `dialog` parameter directly to the original function and accessing it through the `args`, but this approach may seem like a less than ideal workaround.

We appreciate any insights or suggestions on this matter!

Answer №1

Instance fields cannot be accessed in decorator parameters because decorators are applied to classes, not instances.

A workaround is to pass the name of the dialog field, but this requires the field to be made public.

To properly forward the parameters and access this, an arrow function cannot be used. Instead, apply must be used to forward this.

class HeroComponent {
  constructor(public dialog: MatDialog) { }

  @confirmByDialog("dialog") // Compiler check.
  deleteHero() { }
}
function confirmByDialog<K extends string>(dialog: K) {
  return (target: Record<K, MatDialog>, key: string, descriptor: any) => {
    const originalMethod: Function = descriptor.value;

    descriptor.value = function (this: Record<K, MatDialog>, ...args: any[]) {
      const dialogRef = this[dialog].open(ConfirmationDialogComponent);
      return dialogRef
        .afterClosed()
        .subscribe((confirmed: boolean) => {
          if (confirmed) {
            originalMethod.apply(this, ...args);
          }
        });
    };
    return descriptor;
  };
}

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

Unable to retrieve component name using React.Children

While working with react in the nextjs framework, I attempted to create my own dropdown component structured as follows: <Dropdown> <DropdownToggle>Action</DropdownToggle> <DropdownMenu> <DropdownItem>Menu 1</Dr ...

Can type information be incorporated during compilation?

Consider the code snippet below: function addProperties(keys: String[]): Object { // For illustration purposes, this is a specific return return { firstProperty: "first_value", secondProperty: "second_value" }; } export defaul ...

The error message "Type 'IPromise<{}>' is not compatible with type 'IPromise<TemplatesPagingModel>' in typescript version 2.8.0" is displayed

Currently, I am working on an AngularJS framework (version 1.5.8) with the latest TypeScript files (version 2.8.0). However, after updating to the most recent TypeScript version, the code below is not compiling. Implementation of Angular interface: inter ...

Accessing data retrieved from an API Subscribe method in Angular from an external source

Below is the Angular code block I have written: demandCurveInfo = []; ngOnInit() { this.zone.runOutsideAngular(() => { Promise.all([ import('@amcharts/amcharts4/core'), import('@amcharts/amcharts4/charts') ...

Executing Multiple Requests Concurrently in Angular 5 using forkJoin Technique

Important Note The issue lies in the backend, not Angular. The requests are correct. In my Angular5 app, I am trying to upload multiple files at once using rxjs forkJoin. I store the requests in an array as shown in the code below. However, after adding ...

Tips for leveraging angular CLI's async import feature with webpack

I've been attempting to utilize webpack's (2.2.1) async module loading as outlined in the documentation. In addition, I have explored various examples for reference. However, I keep encountering the error message Declaration or statement expecte ...

Exploring the Power of Observables in Angular 2: Focusing on Targeting an Array Nested Within

I encountered a situation where I was successfully looping through objects in an array within my Angular 2 application using observables. In the client service file, my code looked like this: getByCategory(category: string) { const q = encodeURICompon ...

The data type of Subscription: prototype, NOT ASSIGNED

I am encountering the following error when attempting to return a subscription object. Error Message:-------- Type 'Subscription' does not have the prototype and EMPTY properties that are expected from type 'typeof Subscription' Here ...

How to Ensure that the Hidden Value of Select Statement in Angular is Always Displayed as Text

Is there a way to customize the top part of a dropdown menu so that it always displays a specific phrase, like 'Symbols' in this case, regardless of the option selected? Currently, the top part shows the last selected symbol, but I want it to be ...

Is it possible for an ngrx effect to trigger the same action more than once?

I am working with an ngrx effect that needs to trigger multiple calls to the same ngrx action with different parameters. Here is my current approach: @Effect({dispatch: true}) public handleNodeWillReceiveFocus$ = this.actions$ .pipe( ofType( ...

Incorrect date being sent by Mat Date picker

I am encountering an issue with date selection using this input field <mat-form-field class="w-full"> <mat-label>{{ "DATE" | translate }}</mat-label> < ...

Displaying an array object within an array of objects in Angular 2: A guide

Here is an example of a JSON file: { "id": 5, "url": "http://localhost:8000/api/v1/users/5/", "username": "Najmuddin", "email": "", "groups": [ { "id": 1, "url ": "http://localhost:8000/api/v1/groups/1/", ...

Guide on printing in an Ionic application using print.js without the need to open the printer setup page

Our team is currently working on an Ionic web application that utilizes printer functionality. To enable printing, we have integrated the Print.js npm package. However, when we initiate the print method, a setup page displaying details such as printer na ...

I am looking to develop a unique event that can be triggered by any component and listened to by any other component within my Angular 7 application

Looking to create a unique event that can be triggered from any component and listened to by any other component within my Angular 7 app. Imagine having one component with a button that, when clicked, triggers the custom event along with some data. Then, ...

What is the reason behind permitting void functions in the left part of an assignment in Typescript?

Take a look at this Typescript snippet: let action = function (): void { //perform actions }; let result = action(); What makes it suitable for the TypeScript compiler? ...

What is the process for enabling keyboard selections in a Material-UI Select component?

Is there a way to make the MUI Select component keyboard accessible by tabbing into it and using the first letter of the option to auto-select without opening the list? I am looking for a feature where pressing the initial letter selects the first item tha ...

What causes the HTML to not evaluate the values when the pipe is used?

I am currently utilizing a pipe for currency conversion, ensuring that the HTML values remain unevaluated. Let's take a look at the following pipe: transform(value: number, selectedCurrency: string, baseCurrency: string): number { if (selectedCu ...

Can an Angular 9 application access an uploaded file through an HTTP request from the $_FILES array?

I'm currently facing an issue when attempting to send a file to a PHP server using an HTTP request in Angular 9. The problem lies in the fact that the server is not able to receive the uploaded file in $_FILES. Below is the code snippet I have written ...

Using ngFor to destructure two variables simultaneously

When working with Python, I found a way to unpack both variables in each tuple at every iteration. l = [(1, 2), (4, 5), (8, 9)] for k,v in l: print("k = ", k) print("v = ", v) print("-------") # k = 1 # v ...

How will the presence of @types/react impact the higher-level files in my project?

https://i.sstatic.net/TfsLf.png https://i.sstatic.net/RqmMS.png Here is the structure of my directories vue node_modules src react_app node_modules @types/react package.json ...other file package.json Why does the presenc ...