Unleashing the full potential of Angular 7: How a personalized class decorator can

My dilemma lies in the fact that I have a decorator which, when applied on ngOnInit, initiates a console.log.

log.decorator.ts

export function Log(): ClassDecorator {

    // The Decorator Factory
    return (target: Function) => {

        const ngOnInit: Function = target.prototype.ngOnInit;
        target.prototype.ngOnInit = ( ...args ) => {

            console.log('ngOnInit:', target.name);

            if ( ngOnInit ) {
                ngOnInit.apply(this, args);
            }
        };
    };
}

Additionally, there is a HelloComponent that utilizes @Log() and imports a service required in ngOnInit.

hello.component.ts

import { Component, Input, OnInit } from '@angular/core';
import { Log } from './log.decorator';
import { HelloService } from './hello.service';

@Component({
  selector: 'hello',
  template: `<p>Hello! thanks for help and open the browser console for see the error!</p>`,
  styles: [``]
})
// By removing @Log(), helloService.sayHello() functions properly!
@Log()
export class HelloComponent implements OnInit  {

  constructor(private helloService: HelloService){}

  ngOnInit(){
    this.helloService.sayHello();
  }
}

This setup results in an exception:

ERROR TypeError: Cannot read property 'sayHello' of undefined

If I exclude @Log() from HelloComponent, everything works as expected.

It appears that the decorator interferes with the scope of the component at:

ngOnInit.apply(this, args); // line 13: log.decorator.ts

Following this call, this.helloService stands as undefined within the ngOnInit of HelloComponent. Conversely, without @Log(), this.helloService represents an instance of HelloService.

I am seeking advice on rectifying this issue. How should I proceed?

For demonstration purposes, you can access a live example on Stackblitz: https://stackblitz.com/edit/angular-7hhp5n

Answer №1

When using an arrow function, the context of this is bound to the surrounding lexical scope, which in this case is the execution context of the Log function.

If you want to access the component context, it's recommended to use a simple function expression instead:

target.prototype.ngOnInit = function( ...args ) {
   ...
}

Check out the Forked Stackblitz for more details!

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 causes the dispatch property to be undefined in a connected wrapped component within a connected Higher Order Component while using react-redux in conjunction with typescript?

As a new user, I am facing a particular challenge. I am working with a Higher Order Component (HoC) that injects properties into a wrapped component. The HoC itself returns a React.ComponentClass that is connected to the redux store with mapped and dispatc ...

Explore one of the elements within a tuple

Can we simplify mapping a tuple element in TypeScript? I'm seeking an elegant way to abstract the following task const arr: [string, string][] = [['a', 'b'], ['c', 'd'], ['e', 'f']] const f ...

Checking the validity of an asynchronous API response using TypeScript

What is the best way to ensure my API response matches the specified object structure when storing it as an object? Here's an example: const { data } = await axios.get("/form"); How can I validate that the retrieved data adheres to the following inte ...

Storing array elements in a database

Here is the array I am saving to a variable named $multi: { "multicast_id":6026270875633827713, "success":2, "failure":1, } Below is the implementation I am currently using, but it is not working properly: $bony = "INSERT INTO log_notifications(sent_at, ...

Having trouble retrieving information from an asp.net core API in Angular 6

My current project involves a backend .NET Core API and an Angular 6 frontend. I am using the datatables plugin to display data in a grid, but even though the data is being passed from the API, it is not showing up in the grid; the grid appears blank. Bel ...

What is the best way to trigger a parent component to reload from within its child component?

I developed this application using Angular 17 (standalone) and Ionic 7. In the structure, Tab1Page acts as the parent component with "cards", while ItemCardComponent functions as its child showcasing a Swiper carousel of ion-cards that retrieve values from ...

Can you explain the functionality of this MIPS array along with the loop?

Just starting to learn about MIPS and feeling pretty confident with understanding the code, but feeling a bit lost with the given answer/solution. Any assistance would be greatly valued. Take a look at the code below and determine the contents of array ...

Using a PHP associative array to merge tables with identical field names

Currently, I am facing an issue with a particular query where I am trying to retrieve data from an array but struggling to identify the key names: SELECT table_1.*, table_2.* FROM... INNER JOIN... I have looked into similar posts for a solution and fou ...

Looping through user inputs and calculating the sum of all entered values

Having trouble calculating the total of all user-input products? Not to worry, I have a solution for you. The program will prompt the user to select a product and specify its quantity. Then, the user can choose to add more products or proceed with paymen ...

Iterating through a string array and an array containing arrays in Ruby

Help Needed with Ruby Code Here's my current challenge: def iterate1 #method definition within the given class @var3 = @var2.split(" ") #splitting a string into an array @var4 = @var3 @var4.each do |i| #iterating through e ...

Tips for performing a redirect in JavaScript/ReactJS without storing the redirection in the cache

In my TypeScript ReactJS SSR App, I have the following logic: public login() { let error: boolean = false const isLoggedIn: boolean = doSomeLogicHereLikeBackendCheck() if(isLoggedIn) { window.location.href = "/home" // this is getting c ...

A guide on manipulating queryParams within the current route in angular 2 without triggering a page reload

I am currently dealing with the following route: http://localhost:96/#/pages/settings/devices I am looking to add queryParams={name:realTime} to this existing route, like so: http://localhost:96/#/pages/settings/devices?name=realTime Can I manipulate ...

Creating a dropdown menu in Bootstrap 5 without using any of the Bootstrap

In my Angular application, I have a header with icons and pictures that I would like to use as dropdown menus. The code snippet for this functionality is shown below: <li class="nav-item dropdown"> <a class="nav-li ...

Mistake in the push operation for the stack due to a logic

When attempting to perform an insert operation on a stack represented as an array, my program crashes upon entering the first value. typedef struct Stack { int top; int elements[20]; } stack; stack *s; void push(int x) { s->top++; if(s->t ...

Is it feasible to update the value of a FormArray within a FormGroup?

Hey there, I'm new to working with reactive forms and I have a question about updating a FormArray without using the get method. Typically, I would use something like this.editForm.get('ingredients'). However, I would like to use patchValue ...

Troubleshooting the issue with the AWS CodeBuild SAM esbuild integration not functioning

I currently have a Lambda's API Gateway repository in CodeCommit that I successfully build using esbuild with CLI (SAM BUILD and then SAM DEPLOY). Now, I am looking to streamline the building process by integrating it with CodePipeline. I started exp ...

The act of comparing within a for loop

As a newcomer to Java, I encountered an issue while working on a project that involves extracting data by comparing the results obtained from a for loop. The for loop is used to retrieve results from an SQL query, and the code for the for loop is as follow ...

Error encountered following repo duplication

Recently, I upgraded to a new workstation and decided to clone my Angular4 Project repo onto it. After completing the cloning process, I executed: npm install This command is used to fetch all the required node_modules, leading to a multitude of missing ...

Can a type be created that resolves to either of two specific types?

If I have multiple functions that return either a number or a date, is there a way to define a type that encompasses both? For example, instead of: foo1(): number | Date {} foo2(): number | Date {} Can we do something like this: foo1(): NumberOrDate {} f ...

A guide on obtaining data using Graphql and passing it as a prop to a component in Next.js with Typescript

I'm struggling to incorporate a Navbar into my nextjs application using typescript and graphql. For some reason, I can't seem to display the menu items properly. This is my Navbar.tsx component: import Link from "next/link"; import { useState } ...