I have a decorator that on ngOnInit write a console.log
log.decorator.ts
export function Log(): ClassDecorator {
    // 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);
            }
        };
    };
}
and a HelloComponent that use @Log() and import a service used 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: [``]
})
// if you remove @Log(), helloService.sayHello() works!
@Log()
export class HelloComponent implements OnInit  {
  constructor(private helloService: HelloService){}
  ngOnInit(){
    this.helloService.sayHello();
  }
}
but this causes an exception:
ERROR TypeError: Cannot read property 'sayHello' of undefined
if i remove @Log() from HelloComponent it works! 
the decorator seems to destroy the component scope on:
ngOnInit.apply(this, args); // line 13: log.decorator.ts
after this call, this.helloService is undefined in the ngOnInit of HelloComponent, but without @Log(), this.helloService is a HelloService instance.
How do I fix this?
Live example on Stackblitz: https://stackblitz.com/edit/angular-7hhp5n
Arrow function forces context this to be the enclosing lexical context and it's execution context of Log function.
To have component context you should use simple function expression:
target.prototype.ngOnInit = function( ...args ) {
   ...
}
Forked Stackblitz
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With