Enhance an AngularJS directive in TypeScript by implementing a decorator

After developing my own typescript decorator for Component and Inject, the code structure is as follows:

@Component(myModule, {
  selector: 'selector',
  templateUrl: 'template.html',
  bindings: {
    value: '=',
  },
})
@Inject('service')
export class ComponentController {
  value: string;

  constructor(private service: Service) {}
}

The implementation of the decorators is shown below:

export const Component = function(moduleOrName: string | ng.IModule, options: any): Function {
  return (controller: Function) => {
    let module = typeof moduleOrName === 'string' ? angular.module(moduleOrName) : moduleOrName;
    let component = angular.extend(options, { controller });
    module.component(options.selector, component);
  };
};

export const Inject = function(...injections: string[]): Function {
  return (target: Function) => {
    target.$inject = injections;
    return target;
  };
};

Having succeeded with this setup, I attempted to replicate the process for a directive involving either the compile or link functions but encountered difficulties.

@Directive(app, {
  selector: 'selector',
  templateUrl: 'template.html',
  scope: {
    value: '=',
  },
})
@Inject('service')
export class myDirective implements ng.IDirective {
  value: string;

  constructor(private service: Service) {}

  compile(element: ng.IAugmentedJQuery) {
    return this.service.compile(element);
  }
}

The logic behind the Directive decorator is illustrated through the snippet below:

export const Directive = function(moduleOrName: string | ng.IModule, options: any): Function {
  return (directive: Function) => {
    let module = typeof moduleOrName === 'string' ? angular.module(moduleOrName) : moduleOrName;
    let prueba = angular.extend(options, { directive })
    module.directive(options.selector, prueba);
  };
};

Regrettably, upon attempting to create the directive, an error within the Angular library surfaced, displaying the message:

Argument 'fn' is not a function, got Object

Considering these challenges, should this approach be pursued further using decorators, or would resorting to conventional methods be more prudent?

Your insights are greatly appreciated.

Answer №1

Here is the recommended approach:

const createCustomDirective = function(moduleOrName: string | ng.IModule, selector: string): Function {
    return (directive: any) => {
        let module = typeof moduleOrName === 'string' ? angular.module(moduleOrName) : moduleOrName;
        let factory = (...args: any[]) => {
            let options = {
                controller: function () {},
            };
            return angular.extend(new directive(...args), options);
        };
        factory.$inject = directive.$inject;
        module.directive(selector, factory);
    };
};

@createCustomDirective(app, 'selector')
@Inject('service')
export class NewDirective implements ng.IDirective {
    templateUrl = 'template.html';
    scope = {
        value: '=',
    };
    constructor(private service: Service) {}
    compile = function(element: ng.IAugmentedJQuery) {
        return this.service.compile(element);
    }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using NPM packages within the process environment

Can you explain how all these packages are installed in process.env? Also, why is NODE_ENV not visible when I run npm scripts? "start": "NODE_ENV=dev npm run build && npm run watch && npm run tslint" https://i.sstatic.net/OpahA.png Here ...

How can we add a key:value pair at a specific position in an array in Angular 2 using Typescript?

Is there a way to insert a key value pair at a specific index in an array? I am currently struggling with this task. Here is the code I have been working on: this.quiz.push( { "question-no":this.no, "Ans":this.ans } I require this functionality to ...

The ngResource module failed to instantiate within the angular/browserify environment

Recently, I decided to test out browserify in conjunction with Angular. After adding ng-resource to my project using the following command: npm install --save ng-resource I attempted to load it into my code like this: require('angular'); requi ...

Why is it considered an error when an index signature is missing in a type?

Consider the TypeScript code snippet below: type Primitive = undefined | null | boolean | number | string; // A POJO is simply meant to represent a basic object, without any complexities, where the content is unknown. interface POJO { [key: string]: ...

Angular is having trouble with binding

What seems to be the issue in this code snippet? JSFiddle. function SecondCtrl($scope, Data) { $scope.data = Data; $scope.reversedMessage = function(message) { return message.split("").reverse().join(""); }; } ...

Display sibling element upon hovering with AngularJS

Within a single view, I have multiple instances of repeated content elements. Each content element contains an anchor element. My goal is to toggle a class on a sibling element within that specific content element when a user hovers over the anchor. For c ...

Problem with selecting dates in rangepicker

Having trouble with my recursion code for selecting dates in a rangepicker: recurse( () => cy.get('.mantine-DatePicker-yearsListCell').invoke('text'), (n) => { if (!n.includes(year)) { //if year not f ...

Getting access to a function within the same TypeScript file from another exported function in Angular

I'm having trouble accessing a function from another export function within the same TypeScript file. Can anyone help me with this? app.component.ts: import { Component } from '@angular/core'; @Component({ selector: 'app-root', ...

Add the contents of `$scope.data` into a JSON object using

I am trying to update a JSON file with data entered in form elements, but I seem to be encountering some issues. <html ng-app="example"> <div ng-controller="ListController"> <form name="myform" ng-submit="addThis()"> ...

What is the process for deducing nested argument types?

I'm currently experimenting with typescript generics and I'm trying to automatically infer the type of fn, also known as P, but it doesn't seem to be working as intended. If you want to check out the code yourself, visit this interactive Pl ...

What are the best practices for correctly implementing Angularjs ng-repeat?

As a newcomer to angularjs, I am in the process of building an app where the output is already set up correctly. However, I am looking to achieve the same without relying on jQuery, and instead want to utilize the angularjs method using "ng-repeat". Below ...

navigating between AngularJS and Symfony 2

Wondering about integrating routing for a Symfony application in AngularJS. I already have the templates for my Symfony app and looking to use AngularJS for routing these templates. Appreciate any help on this! ...

Tips for monitoring and automatically reloading ts-node when there are changes in TypeScript files

I'm experimenting with setting up a development server for my TypeScript and Angular application without having to transpile the .ts files every time. After some research, I discovered that I am able to run .ts files using ts-node, but I also want th ...

What is the process for converting an Angular UTC timestamp to a local timestamp?

Is it possible to convert a UTC timestamp to a local time timestamp using any function or method? I am sending the timestamp to angular moments, but the server's timestamp is in UTC. ...

Conceal mat-table column when form field is empty

As a newcomer to the world of programming, I am currently tackling a table that includes form fields for filtering purposes. My goal is to dynamically hide or show table columns based on whether a form field has a value or not. In my table.component.ts ...

Difficulty persisting when removing accents/diacritics from a string in Angular with IE 11

When attempting to utilize the String.normalize("NFD").replace(/[\u0300-\u036f]/g, "") method, I encountered an issue in IE11. ERROR TypeError: The object does not support the property or method "normalize" ...

When navigating through the page, Google Maps will display a portion of the map corresponding to your

I recently incorporated the Angular Google map component into my project, using the following code: <google-map [options]="location?.googleMap?.mapOptions" height="100%" width="100%"> <map-marker #marker="m ...

I'm facing an issue with SSRProvider in my NextJs application

My application is developed using NextJs and Typescript, utilizing the react-bootstrap library for creating components. I am facing an issue where I keep receiving an error message stating that When server rendering, you must wrap your application in an &l ...

Recursive Vue components can be implemented using typescript, allowing for

I am working on a TypeScript component that utilizes recursion: <template> <div :style="{ paddingLeft: depth * 20 + 'px' }"> <h1>Level {{ depth }}</h1> <div v-if="depth < 2"> &l ...

The functions of console and splice in AngularJS

While I was trying to delete data from the table, I passed an index from the table and used it in a script. However, I am unsure of what console.log(index) and $scope.facultymembers.splice(index, 1) accomplish. Can someone provide clarification on this? ...