What steps do I need to take to develop a personalized validation directive (an attribute used for validation) in Angular 2.0?

I have embarked on a small project involving Angular 2.0 and TypeScript. From what I understand, Angular 2.0 does not come equipped with built-in validators for the "min" and "max" attributes. I am aware of the process to create a custom validator and associate it using FormBuilder, but I am curious about developing a custom validator directive that can be attached to an attribute. Here is how the HTML appears:

<div class="unit">
<div class="label">Age (13 - 120):</div>
<div class="labelTarget">
    <input id="ageFrm" min="13" max="120" type="number" required=""
    ng-control="age" #age="form" [class.error]="!age.valid"
    [(ng-model)]="ageValue"/> {{age.valid}}
</div>
</div>

The current state of age.valid is always true due to the absence of validators for min and max. I attempted to create my own. Firstly, the custom validation functions:

import {Control} from "angular2/angular2";

export class HealthAppCustomValidators {

static min(min: number): Function {
  return (control: Control): {[key: string]: any} => {
    var v: number = Number(control.value);
    console.log("validating " + v + " against " + min);
    return v < min ?
              {"min": {"requiredMin": min, "actualMin": v}} :
              null;
  };
  }

static max(max: number): Function {
  return (control: Control): {[key: string]: any} => {
var v: number = Number(control.value);
    return v > max ?
              {"max": {"requiredMax": max, "actualMax": v}} :
              null;
  };
   }
}

Next, the directives (based on examination of the source code):

import {Attribute, Control, Directive, forwardRef, Provider, NG_VALIDATORS}   from "angular2/angular2";
import {HealthAppCustomValidators} from "./customValidators";

const MIN_VALIDATOR = new Provider(NG_VALIDATORS, {useExisting: 
forwardRef(() => MinValidator), multi:true});

@Directive({
  selector: '[min][ng-control],[min][ng-form-control],[min][ng-model]',
  providers: [MIN_VALIDATOR]
})
export class MinValidator {

  private _validator: Function;

  constructor(@Attribute("min") min: string) {
    console.log(min);
    this._validator = HealthAppCustomValidators.min(Number(min));
  }
  validate(c: Control): {[key: string]: any} { 
    console.log("validate");
    return this._validator(c); 
 }
}

However, upon attempting to import the directives, the page load fails and presents the following error:

TypeError: validator is not a function
at     http://127.0.0.1:8080/node_modules/angular2/bundles/angular2.dev.js:12990:24
at Array.reduce (native)
at Function.ListWrapper.reduce (http://127.0.0.1:8080/node_modules/angular2/bundles/angular2.dev.js:4206:19)
at http://127.0.0.1:8080/node_modules/angular2/bundles/angular2.dev.js:12989:44
at http://127.0.0.1:8080/node_modules/angular2/bundles/angular2.dev.js:12990:24
at Array.reduce (native)
at Function.ListWrapper.reduce (http://127.0.0.1:8080/node_modules/angular2/bundles/angular2.dev.js:4206:19)
at Control.validator (http://127.0.0.1:8080/node_modules/angular2/bundles/angular2.dev.js:12989:44)
at Control.AbstractControl.updateValidity (http://127.0.0.1:8080/node_modules/angular2/bundles/angular2.dev.js:18871:27)
at  http://127.0.0.1:8080/node_modules/angular2/bundles/angular2.dev.js:14097:14

Any guidance on the proper procedure for achieving this without FormBuilder would be greatly appreciated.

Answer №1

Following Jeremy's recommendation,

The issue was resolved with the introduction of alpha 45, which included support for Validator. Although the error message may have caused confusion (you provided a function, so why didn't it work?), the commit message provided a hint.

Previously, directives could only export validators by providing a function, making it difficult to create validators dependent on directive inputs. Now, in addition to function validators, classes implementing the Validator interface are also supported.

There were no examples available for custom validators in alpha 44 or earlier, making it unclear how they functioned at that time. It is likely that all examples and working validators were updated to be compatible with alpha 45 and later versions.

In any case, upgrading to the latest version of angular2 (alpha 48 is the current version, not alpha 47 as mentioned in the comment) resolved the issue, although at least alpha 45 was required.

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

Adding the ability to export CSV files from Bootstrap Table to an Angular 15 project

Struggling to incorporate the Bootstrap-table export extension into my Angular project without success so far. Visit this link for more information Any assistance or examples would be greatly appreciated. Thank you in advance! This is what I have tried ...

Using Private and Protected Methods in Typescript with React: Best Practices

Currently, I am engrossed in developing a React application utilizing Typescript. In cases where a component needs to offer functionality through a reference, I typically incorporate a public method (public focus() : void {...}). However, I find myself pon ...

Is it possible to create a prototype function within an interface that can group items in an array by a specific property, resulting in an array of objects containing a key and corresponding array of values?

I've been working on this code snippet and I'm trying to figure out how to make it work: Array<T>.groupBy<KeyType> (property): {key: KeyType, array: Array<T> }[]; The code looks like this: type ArrayByParameter<T, KeyType = ...

Dynamic rendering of independent routes is achieved by nesting a router-outlet within another router-outlet

I am working on an angular 2 project with multiple modules. To load each module, I am using the lazy loading technique in this way: { path: 'home', loadChildren: './dashboard/dashboard.module#DashboardModule' }, Currently, I am facing ...

The autocomplete suggestions appear as faded gray text following the cursor in the input field, rather than displaying as a pop-up selection

My website is built using Angular 10 and Angular Material. I am looking to enhance the input suggestions in matInput, but in a unique way that differs from matAutocomplete. Instead of displaying a list of options, I want to show just one suggestion for a ...

Implementing a Map in Typescript that includes a generic type in the value

Here is a code snippet I am working with: class A<T> { constructor(public value: T) {} } const map = new Map(); map.set('a', new A('a')); map.set('b', new A(1)); const a = map.get('a'); const b = map.get(& ...

Angular 2: Integrating a service into a class

I am working on an Angular class that represents a shape. My goal is to be able to create multiple instances of this class using a constructor. The constructor requires several arguments that define the properties of the shape. constructor(public center: ...

Encountering a node module issue when implementing graphql in a TypeScript project

I encountered issues when attempting to utilize the @types/graphql package alongside TypeScript Node Starter node_modules//subscription/subscribe.d.ts(17,4): error TS2314: Generic type AsyncIterator<T, E>' requires 2 type argument(s). node_modu ...

Leverage async-await in conjunction with subscription

I am struggling with a tangled mess of code known as 'callback hell'. Can someone please guide me on how to make use of async-await to simplify the debugging process and tidy up this situation? this.ws.call('vm.image_path', ['Ran ...

The async and await functions do not necessarily wait for one another

I am working with Typescript and have the following code: import sql = require("mssql"); const config: sql.config = {.... } const connect = async() => { return new Promise((resolve, reject) => { new sql.ConnectionPool(config).connect((e ...

Angular 17 component fails to detect signal updates

When I set the value of a signal from component A using a service, it returns null when attempting to access the signal from component B (not the child). I recall this working in Angular 16, did something change in Angular 17? Service @Injectable({ pr ...

The functionality of ellipsis, which consists of three dots, allows the text to expand

I am trying to implement a feature where the extra text is represented by three dots (...) as an ellipsis, and upon clicking the dots, the text should expand and contract. However, the current code only contracts the text and does not expand it upon clicki ...

Implementing Azure Active Directory Authentication for Angular 4 or Angular 2 - Retrieving Access Tokens

I'm in the process of authenticating an Angular 4/Angular 2 app with Azure Active Directory to obtain a token code for passing as a Bearer token when calling a REST API. For this purpose, I've utilized 'ng2-adal' available at https://g ...

Accessing object properties on the fly in TypeScript

I'm currently working on a TypeScript game that features an inventory system with various values, like so: export const Inventory = { food: 0, medicine: 0, rifleAmmo: 0, pistolAmmo: 0 } At the moment, I have a function in place to man ...

Trigger a method within a component when there is a change in the Vuex state

I need to trigger a method inside a component whenever the vuex state changes in TypeScript and Vue.js. While I can access the vuex state value using getters in the template, I am unsure how to access the data within the component class. The vuex state is ...

Terser is causing ng build --prod to fail

When I run ng build --prod on my Angular 7 application (which includes a C# app on the BE), I encounter the following error: ERROR in scripts.db02b1660e4ae815041b.js from Terser Unexpected token: keyword (var) [scripts.db02b1660e4ae815041b.js:5,8] It see ...

The TypeScript compilation failed for the Next.js module

Working on a project using Next.js with typescript. The dev server was running smoothly, and I could see frontend changes instantly. However, after modifying the next.config.js file and restarting the server (later reverting the changes), compilation issue ...

Issue with cookie deletion persists even after using remove('cookie_name') and removeAll() functions in ngx-cookie framework

Having trouble deleting a cookie using ngx-cookie. This is how I am setting the cookie: setCookie(cookie: string) { this.cookieService.put('userDetails', JSON.stringify(cookie), { domain: 'localhost' }); } Even after trying remove(), ...

Navigating the maze of Material UI in React with TypeScript

I have a functioning code, but I am trying to incorporate Material UI into it. However, when I replace 'input' with 'TextField', I encounter the following error: Uncaught (in promise) Error: Request failed with status code 422 at cr ...

Utilize Jasmine to spy on an inner function and return a mock value from the last function call

I'm currently working on a Jasmine test where I have an object structure like this: class User { public getData(): void { return { getPersonalInfo: () => { ... } } } } Typically, I would access it as ...