Unforeseen Behavior in Angular ReactiveForms When Dynamically Setting Validators

I am currently facing an issue with implementing dynamic validations in a ReactiveForm using Angular 4.

The problem I am encountering lies in the unexpected behavior of the SetValidators() function.

My desired behavior is as follows:

The input field should allow empty values, but if the user decides to input something, it must be at least 4 characters long.

As for how it currently behaves, I find it challenging to articulate because I do not fully understand its workings.

You can refer to this plunker for a simple demonstration of the problem I am facing.

In light of this, my question is: What mistakes am I making here? Is my approach correct? Could there be any oversights either in the logic or the HTML implementation?

Answer №1

When subscribing to the ValueChanges of a form control, you may encounter the error Maximum call stack size exceeded. It is advisable to manage input changes using events like keyup instead.

Remember to utilize updateValueAndValidity after adding new Validators to ensure they are applied correctly.

Here is an updated code snippet for your component that should work smoothly now :)

// Our root app component
import {Component, NgModule, VERSION} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import {FormBuilder, FormControl, FormGroup, Validators} from "@angular/forms";
import {FormsModule, ReactiveFormsModule} from "@angular/forms";

@Component({
  selector: 'my-app',
  template: `
    <div>
      <form [formGroup]="userForm">
        <section>
          <div>
            <label>username</label>
            <input (keyup)="inputValueChanged($event)" formControlName="username" type="text">
          </div>
          <button [disabled]="disableSaveButton()">Save</button>
        </section>
      </form>
    </div>
  `,
})
export class App implements OnInit {

  userForm: formGroup

  constructor(private formBuilder: FormBuilder) {
  }

  disableSaveButton(): boolean {
    console.log("is valid:", this.userForm.controls["username"].valid);
    return this.userForm.controls["username"].invalid
  }

  ngOnInit(): void {
    this.userForm = this.formBuilder.group({
      username: '',
    });
  }

  inputValueChanged(event){
    let value = this.userForm.controls["username"].value;
    if (value.length > 0) {
          console.log("should be invalid if less than 4 characters")
          this.userForm.controls["username"].setValidators([Validators.required, Validators.minLength(4)]);

        } else {
          console.log("should be valid")
          this.userForm.controls["username"].setValidators([]); 
        }
        this.userForm.controls["username"].updateValueAndValidity();

  }


}

@NgModule({
  imports: [ BrowserModule, FormsModule, ReactiveFormsModule ],
  declarations: [ App ],
  bootstrap: [ App ]
})
export class AppModule {}

I hope this solution proves helpful to you :)

Answer №2

To ensure the length validation of your form without making it required, simply include validators in the form declaration and eliminate the subscription to valueChanges since it is unnecessary:

this.userForm = this.formBuilder.group({
  username: ['', Validators.minLength(4)],
});

I made changes to the plunker you provided

Answer №3

I recommended creating a customValidator function and then made modifications to it.

ngOnInit(): void {
    this.userForm = this.formBuilder.group({
      username: ['',this.customValidator],
    });
}

customValidator(input: Formcontrol)
{
    let condition: boolean
    ...adjust the condition based on certain variables...
    return condition ? null : {errorDesc: "Not Valid"}
}

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

Leverage Angular CLI in conjunction with Webpack

I'm finding it challenging to integrate cli generate commands into my angular2 project as it's throwing an error. I've opted for the angular2-webpack-starter from git. To utilize the generate command, you must be within an angular-cli proj ...

What is the correct way to declare a class as global in TypeScript?

To prevent duplication of the class interface in the global scope, I aim to find a solution that avoids redundancy. The following code snippet is not functioning as intended: lib.ts export {} declare global { var A: TA } type TA = typeof A class A { ...

Receiving distinct data from server with Ionic 2 promises

Utilizing ionic 2 RC0 with promises to retrieve data from the server, I am facing an issue where I consistently receive the same data in every request due to the nature of promises. Hence, my question is: How can I tackle this problem and ensure differen ...

Incorporate `swagger-ui-express` and `swagger-jsdoc` into your workflow both pre- and post-typescript compilation for optimal

In my project using TypeScript, path mapping, and esbuild for transpiling, I am trying to make both packages in the title work together. The swagger does not seem to work with the transpiled code. To transpile, I use the command rimraf dist && esbu ...

Is there a way to configure eslint to ignore a folder located outside of the root directory?

This is the layout of my project: -lib (git submodule housing a JavaScript library) -A (Vue.js + TypeScript + ESLint app that utilizes lib) -B (another module with an Express app) When running the A app, I encounter eslint errors with the lib submodule: E ...

There was an issue with the DOM where it was reported that the string contains an

HTML document <div> <header>Welcome Page</header> <p><b>{{title}}{{text}}</b></p> <button type="button" class="btn btn-info" (click)="onClickMe($event)">Info</butt ...

What causes the useEffect hook to render twice in a Next.js application?

Within my Next.js application, I am seeking a way to verify whether a user has permission to access a particular page. While using a context, I encountered an issue where my useEffect hook was returning both the updated and default values. How can I ensure ...

Data fetched using React Query

When using React Query to fetch data, the function runs smoothly. After console.logging the 'data' variable from React Query, it prints an array of objects as expected and handles states efficiently between loading, success, error. The issue ar ...

Angular: Enhancing user experience with draggable and droppable items in a flexible list

My issue involves drag and drop divs within a list. However, the divs seem to move in an unpredictable manner. They do not go where I intend them to be placed. Here is the TypeScript code: timePeriods = [ '1', '2', '3', ...

Error with Angular PWA: A fatal error has occurred as the module '@schematics/angular/utility' cannot be located

Trying to execute the command below has been giving me trouble: ng add @angular/pwa Every time I run it, an error pops up saying: An unhandled exception occurred: Cannot find module '@schematics/angular/utility' I attempted to install @schemati ...

Exploring Angular 2's Elementary Observation and Subscription Technique

I am currently attempting to retrieve data from a JSON encoded PHP script API utilizing the following code: export class AppComponent { test = 'Angular is live'; private data; constructor(private http:Http) {} ngOnInit() { ...

Unable to locate the term "module"

I've been working on a TypeScript file that includes an exported function called sum: This script is meant to be run in Node.js. function sum(a:number):number{ return a; } module.exports.sum=sum; I'm encountering some issues and I'm not ...

What is the best way to implement multiple ngIf conditions in Angular code?

Is it possible to set multiple conditions in an ngIf statement? I have created a template for multiple users, but there are some content that I don't want certain users to see, such as Super Admin, Admin, Section Users, Division User, and Unit Leader ...

I encountered an issue with compiling my Docker file containing .NET Core and Angular 7 due to a problem with node sass. The Single Page Application (SPA)

Trying to launch a .NET Core app with Angular using spa middleware in a docker container has been quite the challenge. Initially, I encountered an issue when setting up a new angular app in Visual Studio 2017 Pro with docker support because NPM was missing ...

Is the 'el' property used in Vue along with TypeScript when working with vue-property-decorator/vue-class-component?

Keep this question short and sweet. How would you rewrite the code snippet below using TypeScript, Vue, and vue-property-decorator? @Component({ el: '#app', data() { return { message: 'Hello Vue!' } } }) export defa ...

Transferring an Image File from Angular 8 to a Spring Boot Application

Having trouble sending a file from my Angular 8 app to my Spring Boot server. I've tried using MultiPartFile and HttpServletRequest in Spring, among other methods, with no luck. I'm hoping someone can provide guidance on how to successfully retr ...

Using injected services within static methods may seem tricky at first, but once you

I am exploring the integration of angularjs and typescript in my project. Currently, I am working on creating an Orm factory using typescript but have encountered some challenges. The structure of my factory class is as follows: class OrmModel implements ...

Issue with Filtering Function in Kendo Angular 2 Grid

I have recently started incorporating the Kendo Grid with Angular 2 by following the guidelines in this tutorial: http://www.telerik.com/kendo-angular-ui/components/grid/data-binding/. However, I am facing a challenge as I am unable to locate the filteri ...

Access-Control-Origin header is missing, yet CORS Error persists despite being correctly set

My attempt to execute a Post Request to a PHP API is resulting in the error "no Access-Origin-Control header is set on the resource," despite the header being properly set. Interestingly, when I use Postman to make the request, everything works fine, and e ...

Navigating the upgrade of Ag-Grid from version 21 to version 22 within an Angular 8 environment

Recently, Ag-Grid made significant changes to their code in version 22 by deploying it into modules, primarily from the new packages @ag-grid-community/all-modules or @ag-grid-enterprise/all-modules. However, the documentation on their website is quite unc ...