I am trying to create a decorator in Angular that allows me to mark certain properties of a component as "Options" with a specific type. The goal is to add these marked properties to a list that stores all the options. Later, I would like to call a function called getOptions()
, which should return a Map containing the option names and their corresponding property keys.
I came across this Stack Overflow answer that seems similar to my goal. However, when I tried implementing it, I encountered an error stating "Uncaught TypeError: Cannot assign to read-only property 'Symbol(fields)' of object '[object Object]'".
I would greatly appreciate any help resolving this issue and suggestions or alternative approaches to achieve my desired functionality.
Ideally, I would like to achieve the following:
@Component({...})
export class DashboardComponent {
@OptionType('ColorOption')
color: string = "";
...
ngOnInit(): void {
console.log(getAllProperties()); // Should return <<color, ColorOption>>
}
}
I've also created a Codesandbox, where you can find a working (but not correct) example and can try out your stuff! If you need any more information, feel free to ask!
I've answered it myself. Basically, the decorator was a bit off. I created a fully working Codesandbox for everyone whos curious.
Additionally, in the following you can find the decorator as code:
/**
* OptionType is a decorator function that can be used to annotate class properties with a specific options type.
* @param optionsType - The options type for the annotated property.
* @returns A decorator function that adds the options type to the target object.
*/
export function OptionType(optionsType: OptionsType) {
return function (target: any, key: string) {
// Check if the target object has a property called FIELDS
if (!target[OPTIONS_FIELD_PROP_NAME]) {
// If not, define the FIELDS property as a new Map
Object.defineProperty(target, OPTIONS_FIELD_PROP_NAME, {
value: new Map(),
writable: false, // Prevent overwriting
enumerable: false, // Enable enumeration
configurable: false, // Prevent attribute changes, deletions, etc.
});
}
// Set the optionsType value in the FIELDS map with the key as the property name
target[OPTIONS_FIELD_PROP_NAME].set(key, optionsType);
};
}