Search code examples
angulartypescriptdecoratortypescript-decorator

Angular - how to share a typescript decorator in several libraries


i use the following decorator in order to set string "name" for components:

ComponentRegistry.decorator.ts:

/* eslint-disable @typescript-eslint/no-explicit-any */
export const ComponentRegistry: Map<string, any> = new Map();

export const ComponentLookup = (key: string): any => {
  return (cls: any) => {
    ComponentRegistry.set(key, cls);
  };
};

and i use it like this:

profile-widget.component.ts:

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

import { ComponentLookup } from '../../../decorators/ComponentRegistry.decorator';

@ComponentLookup('ProfileWidgetComponent')
@Component({
  selector: 'dcd-fe-profile-widget',
  templateUrl: './profile-widget.component.html',
  styleUrls: ['./profile-widget.component.css']
})
export class ProfileWidgetComponent
{
}

so i can later load them dynamically into a side-nav menu:

...
  ngAfterViewInit(): void
  {
    // add all the (b4 menu) widgets into the sideNav
    for (let i = 0; i < this.config.widgets.b4.length; i++)
    {
      // get component class reference by it's name as a string
      const classRef = ComponentRegistry.get(this.config.widgets.b4[i]);  

      // add the defined widget to the b4MenuWidgets template
      this.addComponent(classRef, this.b4MenuWidgets);
    }
}

i want to use this decorator in several libraries and in the app itselfe, without duplicating the code, is that possible?


Solution

  • it was so simple... yet documented nowhere

    I simply created another @NgModule (called it 'ui-util')

    and put the decorator code in there and imported that module into any other module I wanted to use the decorator, like this:

    ui-util.module.ts:

    /* eslint-disable @typescript-eslint/no-explicit-any */
    import { NgModule } from '@angular/core';
    import { CommonModule } from '@angular/common';
    
    @NgModule({
      imports: [CommonModule],
    })
    export class UiUtilModule {}
    
    
    // implement decorators here ---- >
    
    export const ComponentRegistry: Map<string, any> = new Map();
    
    export const registerComponent = (key: string): any => {
      return (cls: any) => {
        ComponentRegistry.set(key, cls);
      };
    };
    
    export const findComponent = (key: string): any => {
      return ComponentRegistry.get(key);
    };
    
    • for some reason creating a module and adding the decorator code there and exporting from the module didn't work