Reflect-metadata: check if property has "Output()" decorator

451 Views Asked by At

I am writing an Angular library. An object wraps an Angular component instance, and this object has to subscribe to all subjects marked with Output decorator within the component instance. This is what I have coded so far inside the constructor:

const componentProperties = Object.keys(this.component.instance);
componentProperties.forEach(property => {
    if (!!Reflect.getMetadata('Output', this.component.instance, property)) {
        //do stuff to subscribe
    }
});

Reflect.getMetadata is returning false also analyzing the property "testEvent" inside the angular component:

export class Test2Component implements OnInit {
  public text: string;
  @Output() testEvent = new EventEmitter();
  //...
}

what am I doing wrong?

UPDATE

By the moment, I used this hack:

 componentProperties.forEach(property => {
      if (
        this.component.instance.constructor.__prop__metadata__ &&
        this.component.instance.constructor.__prop__metadata__[property]
      ) {
        this.component.instance.constructor.__prop__metadata__[property].forEach(decorator => {
          if (Reflect.getPrototypeOf(decorator)['ngMetadataName'] === 'Output') {
            let eventName = decorator.bindingPropertyName ? decorator.bindingPropertyName : property;
            this.registerEvent(property);
            this.emitters.push(eventName);
          }
        });
      }
    });

Very ugly, but it works

1

There are 1 best solutions below

0
On

I found a better way to do the same thing through ComponentFactoryResolver:

const factory = componentFactoryResolver.resolveComponentFactory(this.component.componentType);
const eventEmitters = factory.outputs;
eventEmitters.forEach(e => {
  this.registerEvent(e.propName, e.templateName);
  this.emitters.push(e.templateName);
});