1

I have to handle Angular component's destruction event in my external module providing decorating function. Unfortunately I am unable to override ngOnDestroy() method when it contains references to injected services... How can I go over it or achieve the same effect other way?

Plnkr: https://plnkr.co/edit/YtczREB91A3t6rJ1uKks (error in ngOnDestroy() shouldn't be thrown)

If anyone would be interested in this, here is the working version thanks to @estus'es proposition with Symbol(): https://plnkr.co/edit/nnxLswhPUGZR3ycBWojg

2
  • I think you should first implement ngOnit using your service then, use ngOndestroy to destroy it Commented Jul 7, 2017 at 22:21
  • ngOnInit has nothing to do about it. As you can see in the demo router is properly injected inside constructor. Commented Jul 7, 2017 at 22:28

1 Answer 1

1

ngOnDestroy method is overridden with listed decorator. The actual problem with it is that wrong context is applied to originalFunction in

originalFunction.apply(target, arguments);

In case of method/property decorators target argument is class prototype for instance properties/methods:

export const ON_DESTROY_SYMBOL = Symbol();

export function Decorator() {
  return (target: any, propertyName: string) => {
    target[ON_DESTROY_SYMBOL] = target.ngOnDestroy;
    target.ngOnDestroy = function() {
      this[ON_DESTROY_SYMBOL]();
      console.log('Component destroy event successfully handled!');
    }
  }
}

If ngOnDestroy method doesn't necessarily exist but the decorator should be applied any way, it can be class decorator instead, where target is class constructor:

export function Decorator() {
  return (target: any, propertyName: string) => {
    target.prototype[ON_DESTROY_SYMBOL] = target.prototype.ngOnDestroy || () => {};
    target.prototype.ngOnDestroy = function() {
      this[ON_DESTROY_SYMBOL]();
      console.log('Component destroy event successfully handled!');
    }
  }
}

...
Decorator()
Component(...)
class ...
Sign up to request clarification or add additional context in comments.

14 Comments

Yes, it's extended by overriding... The question is: how should I invoke the originalFunction to avoid problems with injected services? Well, it is a property decorator for storing variables in localStorage etc (ngx-store)
Wrap it with try...catch?.. At this point this looks more like XY problem to me. It's not clear why the errors are tolerated in original ngOnDestroy (they obviously shouldn't).
Try-catch doesn't make sense because I don't want to change default behavior and method overridden this way simply stops working...
I want to keep original ngOnDestroy() method's functionality and do some stuff related to the library providing decorator (in the demo is just console.log saying that it's done). Can you think of any other way to achieve it except using additional class decorator? (what doesn't make sense in this project) It looks weird to me since every other property and method is accessible, excluding the injected ones...
Sure, you're welcome. Again, this could be fixed with just originalFunction.apply(this, arguments), but exposing unpatched method on original object usually has more benefits that keeping originalFunction private.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.