Having trouble with implementing a custom validation service in Angular?

I am trying to create a CustomValidationService with a method that validates whether the userName is already in use. However, I encountered an error when attempting to add the userService, which resulted in the following message << Cannot read properties of undefined (reading 'userService') >>.

Below is my implementation of CustomValidationService:

@Injectable({
  providedIn: 'root',
})
export class CustomValidationService {

  constructor(
    private userService: UserService
  ) { }
  userName(control: AbstractControl): { [Key: string]: any } | null {
    const userName: string = control.value;

    var employee: Employee = {
      //Some other fields ...
      "userName": userName
    }

    //This line is causing issue
   const userExists = this.userService.checkIfEmployeeUserNameExists(employee);

    if (!userExists) {
      return null;
    }
    else {
      return { 'userName': true };
    }
  }
}

Here is my implementation of userService:

@Injectable({
  providedIn: 'root'
})
export class UserService {
  public loggedIn = new BehaviorSubject<boolean>(false);
  public employees: Employee[];

  baseUrl = environment.baseUrl;

  constructor(private fb: FormBuilder, private http: HttpClient) { }

      checkIfEmployeeUserNameExists(employee: Employee): Observable<boolean>  {
        return this.http.put<boolean>(this.baseUrl + 'employees/isUserNameUnique', employee)
      }
   }

The call to the CustomValidationService is made within the EmployeeDetailsComponent as shown below:

@Component({
  selector: 'app-employee-details',
  templateUrl: './employee-details.component.html',
  styleUrls: ['./employee-details.component.css']
})
export class EmployeeDetailsComponent implements OnInit {

  constructor(
    private http: HttpClient,
    public translate: TranslateService,
    private route: ActivatedRoute,
    private toastr: ToastrService,
    private userService: UserService,
    private typeService: UserTypeService,
    private menuService: MenuService,
    private _customValidation: CustomValidationService
  ) { }


  ngOnInit() {

    const customValidation = new CustomValidationService(this.userService);

      this.userService.getEmployee(this.employeeId).subscribe(async result => {
        this.employee = await result;
        this.employeeDetailForm = new FormGroup({
          userName: new FormControl(this.employee.userName, [Validators.required, customValidation.userName])
        });
}
}

Answer №1

There are two key issues to address in your code:

  1. The main reason for the error you are experiencing is due to passing a function without binding it. When a function is passed, 'this' becomes undefined. To resolve this, you must first use the bind method.

customValidation.userName.bind(customValidation)

This will eliminate the undefined error. However, your code will still not function as intended because...

  1. You are using an asynchronous operation as a synchronous validator, which will not work. The correct approach is to use it as an asynchronous validator where the validator function returns an Observable or Promise that resolves to either null or validation errors. This is similar to your current setup but functions differently. Async validators should be passed as the third argument of the FormControl constructor.

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

Angular v15 Footer Component Table

In my Angular 15 project, I am attempting to correctly position and utilize the mat table with the following code snippet: <tr mat-footer-row *matFooterRowDef="displayedColumns"></tr>. While the displayedColumns property is functionin ...

Change the ddmmyy date string to dd/mm/yyyy format using TypeScript

When I use the date picker onchange method, the date is passed as a string like ddmmyyyy (20102020) to dd/mm/yyyy. I am unsure of how to convert the date format from ddmmyyyy to dd/mm/yyyy. In the CustomDateParserFormatter, the string needs to be converted ...

Error message: Ionic 3 Angular Native Screenshot encounters a TypeError Issue

i am currently utilizing https://ionicframework.com/docs/native/screenshot/ here is how my code appears: app.module.ts import { Screenshot } from '@ionic-native/screenshot'; providers: [ StatusBar, ThemeProvider, OpportunityServic ...

Unable to modify the date input format in Angular when utilizing the input type date

I am currently working with angular 10 and bootstrap 4. I am trying to update the date format in an input field from (dd/mm/yyyy) to DD/MM/YYYY, but I am facing issues. Below is my angular code: <input type="date" id="controlKey" cl ...

What is the best way to display just one record that has the lowest score out of all the records?

I need help with displaying only 1 record from the DL list that has the lowest score, instead of showing all records. In the example on stackblitz, you can see that for the first record, the DL scores are: 54, 20, and updated. Instead of displaying all 3 ...

Angular validation to ensure future dates are not selected

I am interested in exploring Angular's datepicker functionality and implementing date validation to restrict the selection of future or past dates. For example, if today's date is 17/12/2020, users should only be able to select the current date ( ...

Top Recommendations: Comparing Standalone Components and Modules in Angular Version 14

I'm in need of some clarification on the most effective practices when it comes to utilizing standalone components and modules within Angular 14. With the introduction of standalone components as a new concept in Angular, I am seeking factual guidance ...

How can TypeScript generics' properties be made mutable instead of read-only?

Being new to React and Typescript, I encountered an issue with the AlertDismissable class. I am setting the 'show' property when a request is completed. I followed a sample code and made some modifications. Based on the response received, I dyna ...

Navigate through nested JSON structure without prior knowledge of specific layer names

Is it feasible to iterate through this complex nested object without prior knowledge of the varying views ("A", "B", "C", etc.) it contains? I currently rely on an alphabetic index, but I've been informed that the "view layer" might have diverse names ...

Initial hiccup with HTTP get/post request

Recently, I've encountered an issue while attempting to make HTTP get/post requests in Angular 4. Even after a fresh installation using the CLI, I've come across an unexpected problem. Upon sending a get request for the first time, console.log() ...

Rotating carousel powered by object data

Here is a carousel that I have set up to display images from an object called pictures: <div class="carousel-inner mb-5"> <div *ngFor="let pic of pictures; let i = index"> < ...

Exploring Methods to Define Class Types as Parameter Types in Typescript

Is there a way to pass type information for a class, indicating to the compiler that the provided parameter is not an instance of a class but rather the definition of the class itself? import * as Routes from '../routes'; import * as Entities fr ...

What is the procedure for linking the value (<p>John</p>) to the mat form field input so that it displays as "John"?

Can I apply innerHTML to the value received from the backend and connect it to the matInput? Is this a viable option? ...

Exploring Angular localization using ng2-smart-table

Currently, I am utilizing ng2-smart-table. In my component.ts file, I am setting the column headings. settings = { actions: { add: false, edit: false, delete: false }, columns: { date: { title: 'Date' ...

Typescript with React Hooks

Hey there, everyone! I've been wondering how I managed to make this work, but truth be told, I have no clue why it's actually working. Can anyone provide a technical explanation? import { createContext } from 'react' interface IContext ...

Issue encountered while attempting to download npm for older versions

When utilizing nvm for windows, I typically run 'nvm install' in my VS Code terminal followed by 'nvm use'. However, I have encountered an issue where the command 'npm' is not recognized for older versions of Node. Specificall ...

What is the way to assign a variable to ngClass in Angular?

I'm currently working on creating modals that will display different content based on which button is clicked. Each button should trigger a unique modal to appear, each with its own specific content inside. When a button is clicked, the 'active&a ...

Updating the src attribute within a modal using Angular

Struggling for days to update the src attribute with no success. Any assistance would be greatly valued. Here's the HTML: <!-- Button trigger modal --> <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleM ...

The ngAfterViewChecked function seems to be caught in an endless loop

I am facing an issue where the <cdk-virtual-scroll-viewport> starts from the bottom, but I am unable to scroll up. I suspect that this problem is related to the use of AfterViewChecked. Even after trying AfterViewInit, the issue persists. @ViewChil ...

Uncertainty surrounding refinement in Typescript

I've been diving into the book Programming TypeScript, and I'm currently stuck on understanding the concept of refinement as shown in this example: type UserTextEvent = { value: string; target: HTMLInputElement }; type UserMouseEvent = { value: [ ...