Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find all properties decorated with a certain decoration?

I would like to add decorator to property already decorated with Angular Input decorator.
I need this, because I want to get some (those which are decorated) Input properties for specific Component.

I found very similar question here, but with one big difference (I need it for property not class, so I can not introduce new variable on class as accepted answer proposed).

What I want to achieve is:

export class BaseComponent 
{   
    @Input() id: number;
    @Input() @isFilter id2: number;
    @Input() @isFilter id3: number;

    public getDefaultFilter(): object
    {
        let o: Partial<this> = {};

        //Assign all properties on this(self), which has decorator isFilter, to o!!   

        return o;    //o should be {id2: whatever_is_set, id3: whatever_is_set}
    }
}
like image 542
Makla Avatar asked Feb 28 '18 14:02

Makla


1 Answers

You can use reflect-metadata to store the decorated properties as metadata. E.g. the following code will store the names of all properties decorated with @isFilter(). You can then call getFilteredProperties(this) to get a shallow copy of this containing only the decorated properties.

import 'reflect-metadata';

const metadataKey = Symbol('isFilter');

function isFilter(): (target: object, propertyKey: string) => void {
  return registerProperty;
}

function registerProperty(target: object, propertyKey: string): void {
  let properties: string[] = Reflect.getMetadata(metadataKey, target);

  if (properties) {
    properties.push(propertyKey);
  } else {
    properties = [propertyKey];
    Reflect.defineMetadata(metadataKey, properties, target);
  }
}

function getFilteredProperties(origin: object): object {
  const properties: string[] = Reflect.getMetadata(metadataKey, origin);
  const result = {};
  properties.forEach(key => result[key] = origin[key]);
  return result;
}

You might also want to take a look at the TypeScript documentation for decorators.

Update: Since Plunker appears to have some technical difficulties at the moment I used the opportunity to set up a Stackblitz for the code above. The old Plunker can still be found here.

like image 63
kremerd Avatar answered Nov 01 '22 18:11

kremerd