Angular 9 - Grouping Custom Validators

I have developed an application using Angular CLI 9.0.7 that includes a form with multiple controls requiring validation. To achieve this, I implemented a Custom Validator that can be reused.

However, I am facing an issue where the code within the validator method is not being executed.

Can someone guide me on how to correctly implement and call the isCpf method while following best practices?

This is the Component structure:

        pessoaFisicaFormGroup: this.formBuilder.group({
          numeroCpfForm: ['', [Validators.required, CpfValidator.cpfValido]],
          numeroRgForm: ['', [Validators.required]],
          estadoEmissorRgForm: ['', Validators.required],
        }, { validator: RgValidator.rgValido }), // Two controls need to be validated here

Below is the HTML component:

            <div formGroupName="pessoaFisicaFormGroup" *ngIf="pessoaFisica" class="row">

                <div class="form-group col-sm-12 col-md-6 col-lg-6 col-xl-6">
                    <label for="numeroCpfForm">CPF</label>
                    <input formControlName="numeroCpfForm" 
                           id="numeroCpfForm"
                           type="text" 
                           class="form-control"
                           [ngClass]="{ 'is-invalid': formErrors.numeroCpfForm }" 
                    />
                    <div *ngIf="formErrors.numeroCpfForm" class="invalid-feedback">
                        <div>{{formErrors.numeroCpfForm}}</div>
                    </div>
                </div>

                <div class="form-group col-sm-12 col-md-3 col-lg-4 col-xl-4">
                    <label for="numeroRgForm">RG</label>
                    <input formControlName="numeroRgForm" 
                           id="numeroRgForm" 
                           type="text"
                           class="form-control"
                           [ngClass]="{ 'is-invalid': formErrors.numeroRgForm || formErrors.pessoaFisicaFormGroup }" 
                    />
                    <div *ngIf="formErrors.numeroRgForm || formErrors.pessoaFisicaFormGroup" class="invalid-feedback">
                        <div>{{ formErrors.numeroRgForm ? formErrors.numeroRgForm : formErrors.pessoaFisicaFormGroup}}</div>
                    </div>
                </div>

                <div class="form-group col-sm-12 col-md-3 col-lg-2 col-xl-2">
                    <div class="form­group">
                        <label for="estadoEmissorRgForm">Estado Emissor</label>
                        <select formControlName="estadoEmissorRgForm"
                                id="estadoEmissorRgForm" 
                                class="form-control"
                                [ngClass]="{ 'is-invalid': formErrors.estadoEmissorRgForm }" 
                        >
                            <option selected></option>
                            <option *ngFor="let estado of estados" value="{{estado}}">{{estado}}</option>
                        </select>
                        <div *ngIf="formErrors.estadoEmissorRgForm" class="invalid-feedback">
                            <div>{{formErrors.estadoEmissorRgForm}}</div>
                        </div>
                    </div>
                </div>
            </div>

and here is the implementation of my Custom Validator:

    static rgValido(groupControl: AbstractControl): any | null {
        return (group: AbstractControl): { [key: string]: any } | null => {

            const numeroRgControl: AbstractControl = group.get('numeroRgForm');
            const estadoEmissorRgControl: AbstractControl = group.get('estadoEmissorRgForm');

            if (!numeroRgControl) {
                throw "rgValido::The 'numeroRgForm' field is not defined in the form.";
            }
            if (!estadoEmissorRgControl) {
                throw "rgValido::The 'estadoEmissorRgForm' field is not defined in the form.";
            }

            console.log("Found the controls");

            const numeroRg: string = numeroRgControl.value;
            const estadoEmissorRg: string = estadoEmissorRgControl.value;

            if (numeroRg === '' || estadoEmissorRg === '') {
                return null;
            }
            else {
                if (RgValidator.isRg(numeroRg, estadoEmissorRg)) {
                    return null;
                }
                else {
                    return { 'numeroRgValido': false };
                }
            }
        };
    }

Please review this section as there may be an error around here:

    static rgValido(groupControl: AbstractControl): any | null {
        console.log("This message gets printed");

        return (groupControl: AbstractControl): { [key: string]: any } | null => {

            console.log("But this message does not, as the return statement executes before this line.");

            const numeroCpfControl: AbstractControl = groupControl.get('numeroCpfForm');
            const numeroRgControl: AbstractControl = groupControl.get('numeroRgForm');
            const estadoEmissorRgControl: AbstractControl = groupControl.get('estadoEmissorRgForm');

            if (!numeroRgControl) {
                throw "rgValido::The 'numeroRgForm' field is not defined in the form.";
            }
            if (!estadoEmissorRgControl) {
                throw "rgValido::The 'estadoEmissorRgForm' field is not defined in the form.";
            }

            console.log("Found the controls");

            const numeroRg: string = numeroRgControl.value;
            const estadoEmissorRg: string = estadoEmissorRgControl.value;

            if (numeroRg === '' || estadoEmissorRg === '') {
                return null;
            }
            else {
                if (RgValidator.isRg(numeroRg, estadoEmissorRg)) {
                    return null;
                }
                else {
                    return { 'numeroRgValido': false };
                }
            }
        };
    }

Answer №1

The issue has been successfully resolved by making the necessary adjustments in the code.

While it may not be the most elegant solution, it definitely saves time and gets the job done. I appreciate all the help provided.

    static rgValido(groupControl: AbstractControl): any | null {
        const numeroRgControl: AbstractControl = groupControl.get('numeroRgForm');
        const estadoEmissorRgControl: AbstractControl = groupControl.get('estadoEmissorRgForm');

        if (!numeroRgControl) {
            throw "rgValido::O campo 'numeroRgForm' não está definido no formulário.";
        }
        if (!estadoEmissorRgControl) {
            throw "rgValido::O campo 'estadoEmissorRgForm' não está definido no formulário.";
        }

        const numeroRg: string = numeroRgControl.value;
        const estadoEmissorRg: string = estadoEmissorRgControl.value;

        if (numeroRg === '' || estadoEmissorRg === '') {
            return null;
        }
        else {
            if (RgValidator.isRg(numeroRg, estadoEmissorRg)) {
                null;
            }
            else {
                return { 'rgValido': false };
            }
        }
    }

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

Encountering an issue while attempting to make an in-app purchase with Ionic 3 and Cordova - receiving the error message "Sorry, the item you are trying to

In the process of developing my app with IONIC 3 and Angular 4, I have integrated the following Ionic plugin for in-app purchases: https://ionicframework.com/docs/native/in-app-purchase/ Once the plugin was installed, I included the "play_store_key" in t ...

Loop through an icon in Angular 2 until a specific condition is met

Currently, I am in the process of developing my portfolio website using Angular 2 and I want to incorporate a skill matrix. For testing purposes, I am using a square provided by font-awesome as an example. <tbody *ngFor="let skill of skills"> <tr ...

Utilizing a configuration file with Vue's `use` method

Within my index.ts file, I am setting up the configuration for the Google reCAPTCHA component using a specific sitekey: Vue.use(VueReCaptcha, { siteKey: 'my_redacted_sitekey' }); This setup occurs prior to the initialization of the new Vue({ ...

Exploring the benefits of utilizing TypeScript's async await feature within the Node

I've encountered a challenge trying to accomplish the following tasks simultaneously: Developing in Node.js Coding in TypeScript Implementing async await Facilitating debugging Background: In my TypeScript-based Node.js project, I am incorporating ...

What is the best way to clear the parent component's content from the child component in Angular?

Having an issue with Angular routes. The URLs are functioning properly, but when I navigate to the child component, specifically CreateEventComponent, the parent component's content from EventsComponent is also displayed. How can I make sure that th ...

Transitioning a JavaScriptIonicAngular 1 application to TypescriptIonic 2Angular 2 application

I am currently in the process of transitioning an App from JavaScript\Ionic\Angular1 to Typescript\Ionic2\Angular2 one file at a time. I have extensively researched various guides on migrating between these technologies, completed the A ...

Is it possible to use conditional logic on child elements in formkit?

I am a bit confused about how this process functions. Currently, I am utilizing schema to create an address auto complete configuration. My goal is to have the option to display or hide the fields for manual input. This is the current appearance of the ...

Is it possible to utilize Typescript generics for key filtering in an object?

I have a filter function that has functioning logic, but I am struggling to define its types: export function filter<T>(object: T, ...keys: Array<keyof T>): ??? { let index = -1; const length = keys.length; const result = { ...object }; ...

Tips on optimizing data processing for quicker display with ngFor

I am currently facing an issue with loading a JSON file containing 3500 data. The data appears very slowly on the view, causing the application to work sluggishly. Below is a snippet of the JSON: export class Service { private items = new Arr ...

The input value "HH:MM" does not match the expected format of 'FormatOptions' for this parameter

I created a function that takes in two parameters: data and format. I am attempting to define an ENUM(FormatOptions) for the "format" parameter. However, I encountered the following error: Argument of type '"HH:MM"' is not compatible with param ...

Record the success or failure of a Protractor test case to generate customized reports

Recently, I implemented Protractor testing for our Angular apps at the company and I've been searching for a straightforward method to record the pass/fail status of each scenario in the spec classes. Is there a simple solution for this? Despite my at ...

Pushing out the both /browser and /server directories from an Angular SSR application to Azure Static Web Apps

Continuing from the discussion in this thread, my current challenge involves deploying my Angular SSR app to Azure SWA. I have successfully set it up for running and deployment (using the GitHub Action here): name: Azure Static Web Apps CI/CD on: push: ...

How can I implement a dynamic progress bar using Ionic 4?

I am currently working on developing a progress bar that increases by 1% every time the user clicks a button. This is what my HTML code looks like: <ion-button *ngFor="let progress of progress" (click)="add(progress)">Progress</ion-button> &l ...

Encountering a SassError while trying to create unique themes with Angular Materials

I'm currently in the process of designing a unique theme for Angular Materials by following the instructions provided in this guide:https://material.angular.io/guide/theming#defining-a-custom-theme However, I've encountered an issue while attemp ...

Ways to incorporate Bootstrap components into an Angular application without relying on external modules

I'm attempting to activate Bootstrap 5.3 Tooltips within my Angular 17 application. Within angular.json, I've added bootstrap.bundle.min.js, which includes PopperJS. "scripts": [ "node_modules/bootstrap/dist/js/bootstrap.bundle. ...

What is the best way to dynamically add or utilize a pipe in Angular 8?

I have a special pipe in my Angular 8 application that I created: import { Pipe, PipeTransform } from '@angular/core'; import { MyService} from '../_services/my.service'; @Pipe({ name: 'myPipe' }) export class MyPipe imp ...

Removing invalid characters in a *ngFor loop eliminates any elements that do not meet the criteria

I am facing an issue with my *ngFor loop that is supposed to display a list of titles. fetchData = [{"title":"woman%20.gif"},{"title":"aman",},{"title":"jessica",},{"title":"rosh&quo ...

What is the correct method for implementing a To-Do List?

I am trying to create a to-do list, but I am facing an issue with using splice to remove a specific item e.target.item. It seems like it would be easier if I were using Angular 5. Can anyone assist me with this problem? Thank you. import React, { Compone ...

Determining the type of a single deconstructed variable from an object

My useForm hook is designed to take an object and return several useful functions back, including that object as a state. However, due to TypeScript limitations, the specific type from the initial object cannot be returned because useForm accepts dynamic o ...

Utilizing observables for mapping and filtering data retrieval from the server

I am currently working with an Angular Service that makes a data service call and returns an array of objects with nested data. My goal is to filter this data and only return the matching records. this.behaviourStore.state$ = { "todos": [ { ...