Leverage TypeScript AngularJS directive's controller as well as other inherited controllers within the directive's link function

I am currently developing an AngularJS directive in TypeScript for form validation. I am trying to understand how to utilize the directive's controller and inherit the form controller within the directive's link function.

Thank you in advance!

module app.infrastructure.components.forms {
'use strict';

interface MyIFormController extends ng.IFormController {
    $name: string;
}

interface IMskFormInputController {
    setupDom: (element: any) => string;
    addMessages: (form: ng.IFormController, element: ng.IAugmentedJQuery, name: string, scope: ng.IScope) => void;
    updaterFor: (element: ng.IAugmentedJQuery) => any;
    watcherFor: (form: ng.IFormController, name: string) => any;
}

class MskFormInputController implements IMskFormInputController {

    static $inject = ['$compile'];
    constructor(private $compile: ng.ICompileService) {
    }

    setupDom(element: any): string {
        var name = null;

        var input = element.querySelector("input, textarea, select, ui-select");

        if (input !== undefined && input) {
            name = input.getAttribute("name");
        }

        return name;
    }

    addMessages(form: any, element: ng.IAugmentedJQuery, name: string, scope: ng.IScope): void {

        var messages = "<div class='help-block' ng-messages='" + form.$name + "." + name + ".$error" + "'>" +
            "<div ng-messages-include='/app/infrastructure/directives/forms/messages.html'></div>" +
            "</div>";
        element.append(this.$compile(messages)(scope));
    }

    updaterFor(element: ng.IAugmentedJQuery): any {
        return function (hasError) {
            if (hasError) {
                element.addClass("has-error");
            }
            else {
                element.removeClass("has-error");
            }
        }
    }

    watcherFor(form: ng.IFormController, name: string): any {
        return function () {
            if (name && form[name]) {
                return form[name].$invalid;
            }
        };
    }

}

class MskFormInput implements ng.IDirective {

    constructor() { }

    static factory(): ng.IDirective {
        return new MskFormInput;
    }

    controller = MskFormInputController;
    controllerAs = 'mskFormInputController';
    restrict = 'A';
    require = ['^form'];
    scope = {};
    link(scope: ng.IScope, element: ng.IAugmentedJQuery, attrs: ng.IAttributes, ctrl: any): void {

        //var name = form.setupDom(element[0]);
        //this.controller.addMessages(form[0], element, name, scope);
        //scope.$watch(this.controller.watcherFor(form[0], name), this.controller.updaterFor(element));

    }
}

angular
    .module('app.infrastructure.components.forms.mskFormInputDrtvmdl')
    .directive('mskFormInput', MskFormInput.factory);

}

Answer №1

Let's get started: I strongly believe that this particular question warrants the [angularjs] tag.

Firstly: The communication between directives and controllers should strictly adhere to the scope. Secondly: It is advised to steer clear of manipulating the DOM in the controller; such tasks should be delegated to the directives.

I fail to see any essential role for a controller in the provided code snippet, as their primary duty lies in data manipulation and controlling scope behavior.

It's recommended to delve into the core concepts of angularjs, comprehend their responsibilities, distinguish between each component within the framework. For further insights, refer here and also here. To enhance your skills in writing efficient AngularJS with TypeScript code, consider watching this video.

Below is the refactored code adhering to these aforementioned guidelines:

module app.infrastructure.components.forms {
  'use strict';

  MskFormInput.$inject = ['$compile']
  function MskFormInput($compile: ng.ICompileService): ng.IDirective {

  var setupDOM = (element: HTMLElement) => {
    var name = null;

    var input = element.querySelector("input, textarea, select, ui-select");

    if (input !== undefined && input) {
      name = input.getAttribute("name");
    }

    return name;
  };

  var addMessages = (element: ng.IAugmentedJQuery, form: any, name: string, scope) => {
    var messages =
     `<div class="help-block" ng-messages="${form.$name}.${name}.$error">
        <div ng-messages-include='/app/infrastructure/directives/forms/messages.html'></div>
     </div>`;
    element.append(this.$compile(messages)(scope));
  };

  var invalidForm = (form: ng.IFormController, name: string) => {
    return function() {
      if (name && form[name]) {
        return form[name].$invalid;
      }
    };
  };

  return {
   restrict: 'A',
   require: ['^form'],
   scope: {},
   link: (scope: ng.IScope, element: ng.IAugmentedJQuery, attrs: ng.IAttributes, ctrl: any) => {
     var name = setupDOM(m);
     var form = element[0].form;

     if (!form)
       return;

     addMessages(form, element, name, scope);

     scope.$watch(invalidForm(form, name), (hasError) =>
       element.toggleClass('has-error', hasError)
     );
     }
   };
 }

 angular
   .module('app.infrastructure.components.forms.mskFormInputDrtvmdl')
   .directive('mskFormInput', MskFormInput);
}

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

Error in pairing AngularJS with PHP

This is my code snippet: <script> var app = angular.module('myApp', []); app.controller('customersCtrl', function($scope, $http) { $http.get("http://ip/ss.php") .then(function (response) {$scope.names = response.data.record ...

Installation and execution of TypeScript jQuery / Bootstrap definition file on a local machine using npm typings: A step-by-step guide

Struggling to set up TypeScript jQuery and Bootstrap definition files in my new project using npm typings. Below are the steps I followed: 1- Open cmd, navigate to my project folder, and enter the following commands: npm install typings --global typings ...

Creating Dynamic ion-card Elements in Typescript by Programmatically Changing Values

Currently, I am working on a basic app that retrieves posts from the server and displays them as cards on the screen. At this early stage, one of my main challenges is figuring out how to dynamically add ion-card elements with changing content and headers ...

AngularJS wildcards can be used in filters for a versatile approach

Is there a more efficient way to filter a list of values using wildcards? searchString = "ab*cd" The goal is to retrieve all values that begin with "ab" and end with "cd". One approach I've tried involves splitting the string into multiple substrin ...

"Dealing with conflicts between RMQ and TypeORM in a NestJS

Every time I try to use TypeOrm, RMQ crashes. I can't figure out why. Utilizing the library golevelup/nestjs-rabbitmq has been a struggle for me. I've spent 7 hours trying to resolve this issue. @Module({ imports: [ ConfigModule.f ...

Exploring the concept of data model inheritance in Angular 2

In my Angular2 and ASP.NET Core project, I have set up the following: My C# .NET Core API returns the following classes: public class fighter { public int id { get; set; } public string name { get; set; } public datetime birthdate { get; set; } p ...

What is the best way to implement a Promise Function within a For loop?

Here is a function called sendEmail: public async sendEmail (log: LogMessage): Promise<void> { nodemailer.createTestAccount(async () => { return ServiceFactory.getSystemService().getNetworkPreferences().then(async (networkPreferences) => ...

Creating web components with lit-element, leveraging rollup, postcss, and the tailwind framework for packaging

I have been attempting to package a functional web component that was developed using the lit-element/lit-html with the tailwind framework utilizing the postcss plugin from the rollup packager. Upon conducting a rollup, I discovered the compiled js and ht ...

Customizing the HTMLElement class to modify particular attributes

Is there a way to modify the behavior of an HTMLElement's scrollTop property by adding some extra logic before updating the actual value? The common approach seems to be deleting the original property and using Object.defineProperty(): delete element. ...

Retrieving latitude and longitude from place id in an Angular Google Maps component

Currently utilizing the google-maps component to extract latitude and longitude from Google Maps prediction data. Additionally, I have integrated a search bar using google-maps component. I have successfully implemented a search bar with ngx-google-places ...

Extracting and retrieving the value from the paramMap in Angular/JavaScript

How can we extract only the value from the router param map? Currently, the output is: authkey:af408c30-d212-4efe-933d-54606709fa32 I am interested in obtaining just the random "af408c30-d212-4efe-933d-54606709fa32" without the key "authke ...

Unexpected Memory Drain in Ionic and Cordova on iOS

I've encountered an unusual memory leak in my Ionic and Cordova application. This leak is not present when running the app in Chrome, but it clearly appears when I test the app. The issue arises when I need to iterate through a large data set and assi ...

What causes Enum[Enum.member] to be undefined in the TypeScript playground on codepen.io?

My intention was to test out some type settings on TypeScript playground at codepen.io, but I encountered an unexpected issue: enum Order { Asc = 'asc', Desc = 'desc' } console.log(Order[Order.Asc]); // undefined in codepen.io ...

I am encountering an unresolved error: [$injector:modulerr] Problem on my AngularJS application related to routing

Attempting to develop an angular application, encountering the following error: The issue is outlined in this link: http://errors.angularjs.org/1.3.13/$injector/modulerr?p0=app&p1=Error%3A%20…ttp%3A%2F%2Flocalhost%3A8888%2FHotelAdmin%2Fjs%2Fangular. ...

This function provides a service and does not return any value

When calling my service function, I am storing a boolean value in a variable to determine if a user is an admin or not. However, even though I receive the result (true or false), when assigning it to the variable vm.isAdmin, it shows up as undefined. vm ...

Angular 4 - Sum all values within a nested array of a data model

I am working with an array of Models where each object contains another array of Models. My goal is to calculate the sum of all the number variables from the nested arrays using the code snippet below. Model TimesheetLogged.ts export interface Timesheet ...

Arranging Angular Cards alphabetically by First Name and Last Name

I am working with a set of 6 cards that contain basic user information such as first name, last name, and email. On the Users Details Page, I need to implement a dropdown menu with two sorting options: one for sorting by first name and another for sorting ...

Unable to retrieve input value in ReactJS with TypeScript

I've just started learning Typescript and I encountered an error while trying to console.log the input field value. Any tips or suggestions on how to handle this? Here's my code: class Register extends Component<{},userState> { state = { ...

Retrieve the value of a property within the same interface

Is there a way to access an interface prop value within the same interface declaration in order to dynamically set types? I am attempting something like this: export type MethodNames = "IsFallmanagerUpdateAllowed" | "UpdateStammFallmanager& ...

Broadcasting events across the entire system

I'm trying to accomplish something specific in Angular2 - emitting a custom event globally and having multiple components listen to it, not just following the parent-child pattern. Within my event source component, I have: export class EventSourceCo ...