Extending an Angular 5 component using metadata

Viewed 3448

When my project was using Angular 2 and Angular 4, I was able to use this useful decorator for making a component extend another component:

// Modified from https://medium.com/@ttemplier/angular2-decorators-and-class-inheritance-905921dbd1b7#.s9pf0649f
// by Thierry Templier.

import { Component } from '@angular/core';

export function ComponentExtender(annotation: any): ((target: Function) => void) {
  return function(target: Function): void {
    let parentTarget = Object.getPrototypeOf(target.prototype).constructor;
    let parentAnnotations = Reflect.getMetadata('annotations', parentTarget); // TODO: Doesn't work in Angular 5, returns undefined.
    let parentAnnotation = parentAnnotations[0];

    Object.keys(parentAnnotation).forEach(key => {
      if (parentAnnotation[key]) {
        if (!annotation[key]) {
          annotation[key] = parentAnnotation[key];
        }
      }
    });

    let metadata = new Component(annotation);

    Reflect.defineMetadata('annotations', [ metadata ], target);
  };
}

With this you could create a component class that extended an another component class, using @ComponentExtender instead of @Component, and inherit things from the superclass like the template and style if those things did not need to be changes in the subclass component.

This no longer works now that I've moved my project to Angular 5. The annotations metadata is undefined.

Does this perhaps have something to do with AOT compilation (even though I haven't selected that option)? Can anyone think of a way to revive what this decorator used to do for Angular 2 and Angular 4?

2 Answers

You can get the annotation via target['__annotations__'][0].

There is also '__paramaters__' and '__prop__metadata__', see source of decorators.ts

Note: According to the Angular Blog, the build optimzer now is used by default for production builds, so the annotations will not be available at runtime.

Disclaimer: This is hacky and an implementation detail, so it should never be used in production code!

Related