Designing a unique directive for validating multiple fields (such as password confirmation) in Angular 6

After creating a component called set-pass, I aimed to handle the password and confirm password functionalities within this component. To achieve this, I experimented by crafting a custom directive (confirm-equal-validator.directive.ts) located inside the shared folder.

Here's an overview of my component files:

set-pass.component.html

    <form >
      <mat-form-field >
        <input matInput name="password" placeholder="New password" [type]="hide ? 'password' : 'text'" [formControl]="passFormControl" required>

        <mat-icon matSuffix (click)="hide = !hide">{{hide ? 'visibility' : 'visibility_off'}}</mat-icon>
        <mat-error *ngIf="passFormControl.hasError('required')">
            Please enter your new password
          </mat-error>
      </mat-form-field>

      <mat-form-field >
        <input matInput name="confirmPassword"  appConfirmEqualValidator="password"  placeholder="Confirm password" [type]="hide ? 'password' : 'text'" [formControl]="confirmFormControl" #confirmPasswordControl="ngModel" required>

        <mat-icon matSuffix (click)="hide = !hide">{{hide ? 'visibility' : 'visibility_off'}}</mat-icon>
        <mat-error *ngIf="confirmFormControl.hasError('required')">
          Confirm your password
          </mat-error>
          <mat-error *ngIf="confirmFormControl.hasError('notEqual')">
            Confirm your password
            </mat-error>
      </mat-form-field>
   </form>

set-pass.component.ts

    import {Component, OnInit } from '@angular/core';
    import {FormControl, FormGroupDirective, NgForm, Validators} from 
         '@angular/forms';
    import {ErrorStateMatcher} from '@angular/material/core';

     @Component({
       selector: 'ylb-set-pass',
       templateUrl: './set-pass.component.html',
       styleUrls: ['./set-pass.component.css']
       })
     export class SetPassComponent {

        passFormControl = new FormControl('', [
        Validators.required,
         ]);
           confirmFormControl = new FormControl('', [
          Validators.required,
        ]);
   }

confirm-equal-validator.directive.ts(present inside shared folder)

    import { Validator,AbstractControl,NG_VALIDATORS } from '@angular/forms';
    import { Directive,Input} from '@angular/core';



    @Directive({
       selector: '[appConfirmEqualValidator]',
       providers: [{
            provide: NG_VALIDATORS,
            useExisting: ConfirmEqualValidatorDirective ,
            multi:true
        }]
     })

   export class ConfirmEqualValidatorDirective implements Validator{
     @Input() appConfirmEqualValidator:string;
      validate(control: AbstractControl):{[key:string]:any} | null{
        const controlToCompare = 
    control.parent.get(this.appConfirmEqualValidator);
        if(controlToCompare && controlToCompare.value !== control.value){
           return{'notEqual':true};
         }
         return null;
       }
     }

I have imported this component in app.module.ts like this

    import { ConfirmEqualValidatorDirective } from './shared/confirm-equal-validator.directive';

I took all necessary steps as outlined in this video tutorial:

    https://www.youtube.com/watch?v=YhazkQd59Hk

An error was reported in CMD as follows:

    ERROR in src/main.ts(5,29): error TS2307: Cannot find module './environments/environment'.

My goal is to implement the confirm password feature using Material components exclusively, similar to this example:

https://i.sstatic.net/Ps1A6.png

Answer ā„–1

Forget about the error you encountered, there's actually a simpler method for verifying if passwords match.

Assuming you have two form controls set up like this:

<input matInput name="password" placeholder="New password" [formControl]="passFormControl" required (blur)="checkPasswordControls()">
<input matInput name="password" placeholder="Confirm password" [formControl]="confirmFormControl" required (blur)="checkPasswordControls()">
checkPasswordControls() {
  if (this.passFormControl.value !== this.confirmFormControl.value) {
    this.passFormControl.setErrors({ notEqual: true });
    this.confirmFormControl.setErrors({ notEqual: true });
  } else {
    this.passFormControl.setErrors(this.passFormControl.errors ? { ...this.passFormControl.errors } : null);
    this.confirmFormControl.setErrors(this.confirmFormControl.errors ? { ...this.confirmFormControl.errors } : null);
  }
}

Now, whenever you move away from either input field, your component will verify if the values of the two forms match. If they don't match, an error will be added to both inputs.

This approach eliminates the need for the directive you were using before. Since you only use the directive once, it is unnecessary. This method is also more concise, easy to understand, and clearer to follow.

Answer ā„–2

If you're encountering the error "Cannot find module './environments/environment', make sure to check if there is a folder named 'environment' in your current directory. For example, it should be located in src>app>environment>environment.ts or environment.prod.ts. The issue might be that your main module has a dependency on the 'environment' folder which is missing. This could be detected by smart editors like VSCode.

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

Typescript: Error encountered. Invalid input: Non-string value provided to `ts.resolveTypeReferenceDirective`

A while back, I developed an npm command line application that was working perfectly fine. However, after a recent update due to changes in TypeScript versions over time, I encountered an error when trying to run the package. The error message I received w ...

Angular HighCharts - Retrieving chart data via API

My goal is to populate the data property of my chart with values obtained from an external API: . I've defined an Interface that matches the structure of the data: export interface ChartData{ item1: number; item2: number; ...

Is it possible to define multiple regular expressions for a single field using yup in a form validation?

My goal is to validate an input to only accept URLs in Google Maps format. There are three possible valid outputs for a Google Maps URL: (for Google Maps app) (I only want to focus on ) (when sharing directly from Google Maps) Currently, I am able to ...

Adding up the numbers with JavaScript

Hello everyone, I've been working on some transformations and now I'm left with an array of objects: Can anyone help me come up with a flexible function that will generate a new object where each data[i] is the sum of values from the previous ob ...

Issue with TypeScript in VSCode: "Unable to save file 'x' as it would overwrite the input file."

As I work on improving my JavaScript quality with TypeScript in VSCode, Iā€™m encountering an issue with my tsconfig.json file. It keeps throwing errors when trying to write my .js files, specifically displaying the message: "Cannot write file 'lib/c ...

Objects That Are Interconnected in Typescript

I have been delving into TS and Angular. I initially attempted to update my parent component array with an EventEmitter call. However, I later realized that this was unnecessary because my parent array is linked to my component variables (or so I believe, ...

What is the best way to attach a DOM element to an Angular 2 TestBed?

I was wondering if it is possible to add a DOM element to the test DOM before running tests. I'm new to testing, but something like fixture.debugElement.prepend('div') might work. However, I understand that this approach may indicate a desig ...

When executing NextAuth with the given auth options, it raises an error message stating "Incompatibility of types for 'adapter.createUser' between these specific types."

Currently, I am working on a project using Next.js 14 and attempting to configure NextAuth with the app/router. Unfortunately, I have encountered a type error that is proving difficult to resolve. Below is my route.ts file: // ./app/api/[...nextauth]/rout ...

I encountered an error while attempting to create an npm package from a forked repository on GitHub

Check out this GitHub repository: https://github.com/jasonhodges/ngx-gist Upon running the package command, I encounter an error: rimraf dist && tsc -p tsconfig-esm.json && rollup -c rollup.config.js dist/ngx-gist.module.js > dist/ngx- ...

Creating a Typescript interface that includes keys from another interface

interface A{ a: string; b: string; c: string; // potentially more properties } interface B{ [K in keyof A]: Boolean; } What could be the issue with this code? My goal is to generate a similar structure programmatically: interface B{ ...

Angular 5 - capturing form inputs - activating event upon selecting suggested values

When I click on suggested values below the input field, the (click)="doSomething()" event doesn't fire. How do I handle this issue? I would like to be able to type something in the input field and then have an event triggered when clicking on the su ...

Mastering the nesting of keys in Typescript.Unlock the secrets of

I encountered a situation where the following code snippet was causing an issue: class Transform<T> { constructor(private value: T) {} } class Test<T extends object> { constructor(private a: T) {} transform(): { [K in keyof T]: Transfo ...

Ways to verify if the output from translate.instant has been properly translated at least once

With ngx-translate, I have implemented the following function and my goal is interface IWidgetFilterValue = { label: string; value: string; } getSortedOptions(filterOptionsArr: IWidgetFilterValue[]): IWidgetFilterValue[] { const filterOptionsArrNew = ...

Why is Karma not recognizing my typings definition file?

Setting up Karma for my React app has proven to be a challenge. Here is the stack I am working with: Karma React Webpack Typescript To make my React app function properly, I require some custom typings in src/typings.d.ts: declare module '*.json&a ...

Exploring the difference between loop and stream patterns in Azure Service Bus message receiving operations

I am currently setting up the Azure Service Bus messaging infrastructure for my team, and I am working on establishing best practices for developing Service Bus message receivers. We are in the process of creating a new service to consume the Service Bus m ...

Using ts-node throws an error when checking if window is equal to "undefined" using typeof

I encountered an issue with my code where I used typeof window == "undefined" to check for a browser environment. When running this code with ts-node, I ran into the following error: typings/Console.ts:36:10 - error TS2304: Cannot find name 'window&a ...

Modifying column array properties using jsstore

I am working with a jsstore table called tblInvoice const tblInvoice: ITable = { name: "invoice", columns: { // Here "Id" is name of column id: { autoIncrement: true, primaryKey: true, notNull: false }, branchId: { ...

Despite reaching a video readystate of 4 in HTML5, the video still hangs and does not play smoothly

Using html5, I am currently working with video and audio. I have encountered an issue where sometimes the video hangs even after its readyState === 4. The cause of this problem is unclear to me. I aim for a solution where if the video's readyState = ...

What is the best approach for replacing numerous maps within an rxjs observable array?

Is there a more efficient way to retrieve only 3 items from an array? If you have any suggestions, I would appreciate it! Thank you. loadAsk!: Observable<any[]>; this.loadAsk.pipe( map(arr => arr.sort(() => Math.random() - .5)), map((item ...

What is preventing NgClass from applying the CSS styles?

I'm currently facing an issue in Angular2 where I am trying to apply different styles using ngClass within an 'NgFor' loop, but for some reason, it's not working as expected. Apologies for any language errors. <div class='line ...