Update 2.3.0
Now you can use object inheritance for components.
You can see more detailed information in this commit https://github.com/angular/angular/commit/f5c8e0989d85bc064f689fc3595207dfb29413f4
Old version
1) If you have a class:
abstract class BaseClass { @HostListener('window:beforeunload') beforeUnloadHander() { console.log('bla'); } }
then he will work
Plunger example (put spaces somewhere in the editor and view console)
, but be careful , because Angular2 does not support full inheritance - Binding problem and @ViewChild a>
But it is still unclear why the solution with @HostListener did not work in the first place
In particular, if you have a property decorator on your derived component, it will not work. For example, let's say we have the following code:
abstract class BaseClass { @HostListener('window:beforeunload') beforeUnloadHander() { console.log(`bla-bla from${this.constructor.name}`); } } @Component({ selector: 'derived-one', template: '<h2>derived-one</h2>' }) export class DerivedOne extends BaseClass { @Input() test; }
Plunker
It will be converted to javascript, for example:
var core_1 = require('@angular/core'); var BaseClass = (function () { function BaseClass() { } BaseClass.prototype.beforeUnloadHander = function () { console.log("bla-bla from" + this.constructor.name); }; __decorate([ core_1.HostListener('window:beforeunload'), __metadata('design:type', Function), __metadata('design:paramtypes', []), __metadata('design:returntype', void 0) ], BaseClass.prototype, "beforeUnloadHander", null); return BaseClass; }()); var DerivedOne = (function (_super) { __extends(DerivedOne, _super); function DerivedOne() { _super.apply(this, arguments); } __decorate([ core_1.Input(), __metadata('design:type', Object) ], DerivedOne.prototype, "test", void 0); DerivedOne = __decorate([ core_1.Component({ selector: 'derived-one', template: '<h2>derived-one</h2>' }), __metadata('design:paramtypes', []) ], DerivedOne); return DerivedOne; }(BaseClass));
We are interested in the following lines:
__decorate([ core_1.HostListener('window:beforeunload'), __metadata('design:type', Function), __metadata('design:paramtypes', []), __metadata('design:returntype', void 0) ], BaseClass.prototype, "beforeUnloadHander", null); ... __decorate([ core_1.Input(), __metadata('design:type', Object) ], DerivedOne.prototype, "test", void 0);
HostListener and Input are property decorators ( propMetadata key). This method will define two metadata records - on BaseClass and on DerivedOne

Finally, when angular2 will retrieve metadata from the DerivedOne class, it will only use its own metadata:

To get all the metadata, you can write your own decorator, for example:
function InheritPropMetadata() { return (target: Function) => { const targetProps = Reflect.getMetadata('propMetadata', target); const parentTarget = Object.getPrototypeOf(target.prototype).constructor; const parentProps = Reflect.getMetadata('propMetadata', parentTarget); const mergedProps = Object.assign(targetProps, parentProps); Reflect.defineMetadata('propMetadata', mergedProps, target); }; }; @InheritPropMetadata() export class DerivedOne extends BaseClass {
Here is a demo
2) If you have done the following:
abstract class BaseClass constructor(){ window.onbeforeunload = function(){ console.log('bla'); }; } }
then it will only be called once because you redefine the window.onbeforeunload handler each time. Instead, you should use the following:
abstract class BaseClass { constructor(){ window.addEventListener('beforeunload', () =>{ console.log(`bla-bla from${this.constructor.name}`); }) } }
Plunger example
3) Finally, if you have a base class, as shown below:
abstract class BaseClass { beforeUnloadHander() { console.log(`bla-bla from${this.constructor.name}`); } }
then you should use the correct syntax ( which you are missing the bracket ) in the decorator property:
host: {'(window:beforeunload)': 'beforeUnloadHander()' }
Plunger example
Hope this helps you!