angular2 the custom template validator is encountering outdated values

I've been struggling with a specific issue for quite some time now. I'm working on setting up an Angular 2 custom validator that checks if a number falls within a certain range. When used as follows, everything functions correctly:

<input type="text" id="doseSimple" class="form-control"
       required 
       name="doseSimple" 
       [(ngModel)]="doseSimple"
       #doseControl ="ngModel"
       validateRange
       from="2"
       to="20"
       >

<div *ngIf="doseControl.errors && (doseControl.dirty || doseControl.touched)">
   <span *ngIf="doseControl.errors.tooSmall">Too small</span>
   <span *ngIf="doseControl.errors.tooBig">Too big</span>
</div> 

However, in my scenario, the validation process is a bit more complex. It involves a dropdown menu where the validity range depends on the selected option. There's an event tied to the dropdown that sets doseFrom and doseTo properties accordingly:

  <input type="text" id="name" class="form-control"
         required 
         name="doseComplex" 
         [(ngModel)]="doseComplex"
         #doseComplexControl ="ngModel"
         validateRange
         [from]="doseFrom"
         [to]="doseTo"
         >
  <div *ngIf="doseComplexControl.errors && (doseComplexControl.dirty || doseComplexControl.touched)">
     <span *ngIf="doseComplexControl.errors.tooSmall">Too small</span>
     <span *ngIf="doseComplexControl.errors.tooBig">Too big</span>
  </div> 

The issue I'm facing is that the validator evaluates the value using the previous from and to selections instead of the current ones. How can I resolve this problem?

To provide a clearer picture, I've set up a Plunker showcasing the dilemma: https://plnkr.co/edit/C0sbL8pRwsZcEZ5r1ODY?p=preview

Answer №1

To achieve this functionality, I would utilize the registerOnValidatorChange method as shown below:

export class RangeValidator implements Validator {
  @Input()
  get from() {
    return this._from;
  }
  set from(value: number) {
    this._from = value;
    if (this._onChange) this._onChange();
  }

  @Input()
  get to() {
    return this._to;
  }
  set to(value: number) {
    this._to = value;
    if (this._onChange) this._onChange();
  }

  validate(c: FormControl): { [key: string]: boolean; } {
    ...
  }

  private _from: number;

  private _to: number;

  private _onChange: () => void;

  registerOnValidatorChange(fn: () => void): void { 
    this._onChange = fn; 
  }
}

Check out the modified Plunker for more details.

You can remove the usage of updateValueAndValidity.

For further information, you may refer to the Angular source code here:

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

Navigating through errors in my Dockerfile while running Angular

As a complete novice in the world of Docker (although quite comfortable with the rest of my tech stack), I followed along with the Docker guide and ended up with this Dockerfile: FROM angular/ngcontainer:latest WORKDIR /ClientApp COPY . . RUN npm install - ...

Retrieving data from Node.js within an Angular application

I am currently working on retrieving data from MongoDB and displaying it on my website. However, I am facing an issue in sending the entire fetched object to a specific port (the response) so that I can retrieve it from Angular. I also need to know how to ...

Tips for bringing in a text file within a NodeJS application using TypeScript and ts-node during development

I am currently developing a NodeJS/Express application using TypeScript, Nodemon, and ts-node. Within this project, there is a .txt file that contains lengthy text. My goal is to read the contents of this file and simply log it to the console in developmen ...

I am encountering an error stating "Cannot locate module 'nestjs/common' or its related type declarations."

I am currently working on a controller in NestJS located in the file auth.controller.ts. import { Controller } from 'nestjs/common'; @Controller() export class AppController {} However, I encountered an error that says: Error TS2307: Cannot fin ...

Using Angular 4 to populate a form and ensure it remains untouched

Designed an update form that is pre-populated with information. I am aiming for the button to be inactive until any changes are made within the form The form group utilizes valueChanges to detect when information has been modified However, even when I u ...

What are some best practices for integrating ES2020 into an Angular project?

Below is the content of my tsconfig.json file: { "compileOnSave": false, "compilerOptions": { "baseUrl": "./", "outDir": "./dist/out-tsc", "sourceMap&q ...

Using TypeScript to retrieve a strongly typed promiseValue from an angular $modalInstanceA

New to TypeScript Question: I'm working on returning a strongly typed promise from angular's $modalInstance. Here is an example of what I have: this.$modal.open(options).result.then(result => { At the moment, 'result' is of typ ...

The inversify middleware is executed a single time

I utilize Inversify for object binding in the following manner: container.applyMiddleware(loggerMiddleware); let module = new ContainerModule((bind: interfaces.Bind) => { bind<Logger>(TYPES.Logger).toConstantValue(logger); bind<ILogger ...

JavaScript has a feature called "functions" which allow the declaration of named blocks of

Currently, I am developing an Electron app in typescript. In my main.ts file, I have instantiated a custom CommunicationProvider class object. What I want is for this class to declare multiple methods (specified in an interface that it implements) but have ...

Matching the value of an Angular 4 FormGroup with an item in an array

In order to ensure that the input of the country in my form matches one of the countries in my predefined country list, I am looking to implement a custom validation function for my form group. Here is the list of available countries: this.sharedService. ...

Bringing in information from a TypeScript document

I'm having trouble importing an object from one TypeScript file to another. Here is the code I am working with: import mongoose from "mongoose"; import Note from './models/notes'; import User from './models/users'; import ...

A comprehensive guide on displaying data in Angular using an API

I have encountered an issue while trying to display data from an API in the 'home.component.html'. Although my 'home.component.ts' successfully fetches the data from the service, I'm facing difficulty rendering it in 'home.com ...

Choose the material and eliminate any gaps

Is there a preferred method for eliminating empty space in Material select/input fields? I am looking to ensure the field width matches the content size. https://i.stack.imgur.com/ZmgKK.png Visit https://material.angular.io/components/select/overview for ...

What are the steps for implementing the ReactElement type?

After researching the combination of Typescript with React, I stumbled upon the type "ReactElement" and its definition is as follows: interface ReactElement<P = any, T extends string | JSXElementConstructor<any> = string | JSXElementConstructor< ...

ServiceWorker has responded with a 503 OK status code

Recently, I implemented @angular/service-worker to create a SW for my angular4 web application. However, I encountered an issue after updating the ngsw-manifest.json file to handle dynamic requests from the server - now, whenever I go offline (after initia ...

What is the procedure for utilizing custom .d.ts files in an Angular 15 project?

Currently, within my Angular 15 project, I am utilizing a package called bootstrap-italia. This particular package is dependent on the standard Bootstrap package and includes additional custom components and types. However, it should be noted that this pac ...

I'm encountering a 502 error while trying to use Supabase's signInWIthPassword feature

Despite all authentication functions working smoothly in my React, TypeScript, and Supabase setup, I'm facing an issue with signInWithPassword. In my context: I can successfully signIn, create a profile, and perform other operations like getUser() an ...

Incorporate a Custom Icon into NbSelect

I am currently utilizing Nebular in a project, where multiple dropdowns are being used as shown below: <nb-select fullWidth placeholder="Office" formControlName="office"> <nb-option value="Office_A"&bt;Office A</n ...

Exploring the world of publishing Angular 2 applications

I recently created an Angular 2 application using npm, but as a beginner I am unsure of some aspects. For instance, when I publish my application, I typically use npm publish to share it on my npm account online. However, I am wondering if there is a way t ...

Why does the error "property undefined" keep popping up even though I've already declared it?

Currently, I am facing an issue with toggling the theme in my project. I am encountering difficulties with the types involved, and I am unsure whether the problem lies within my TypeScript configuration or my actual code itself. I attempted to replicate t ...