Unlocking 'this' Within a Promise

I seem to have an issue with the 'this' reference in the typescript function provided. It is not correctly resolving to the instance of EmailValidator as expected. How can I fix this so that it points to the correct instance of EmailVaildator, allowing me to access _registerServices?

class EmailValidator {

    constructor(private _registerServices: RegisterServices) { }

    isAvailable(c: AbstractControl): Promise<ValidationResult> {
        let q = new Promise((resolve, reject) => {
            this._registerServices.emailIsAvailable(antiForgeryToken(), c.value)
                .then(result => {
                    // Need to actually check the result.
                    resolve({ "emailtaken": true })
                },
                error => {
                    // Need to communicate the server error? Probably not.
                    resolve({ "servererror": true })
                });
        });

        return q;
    }
}

Answer №1

You may be experiencing an issue with losing functionality due to how you are using isAvailableEmail as a "raw" function in this scenario:

email: ['', Validators.required, this._emailValidator.isAvailableEmail]

To resolve this, you should consider binding it to this by using the fat arrow syntax:

email: ['', Validators.required,
  (control) => { this._emailValidator.isAvailableEmail(control) }
]

Answer №2

Upon investigation, it was revealed that the 'this' reference turned out to be undefined even when used in the following context:

class EmailValidator {

    constructor(private _registerServices: RegisterServices) { }

    isAvailable(c: AbstractControl): EmailValidator {
        return this; // The 'This' reference is undefined!
    }
}

It seems that the issue might have stemmed from how the method was invoked, potentially involving passing a non-static method when a static method was expected:

...
this.registerForm = fb.group({
    email: ['', Validators.required, this._emailValidator.isAvailableEmail],
    password: ['', Validators.compose([Validators.required, Validators.minLength(8)])],
    phoneNumber: ['', Validators.required],
    country: ['', Validators.required]
    });
...

If someone could provide guidance on what exactly is happening here, it would be greatly appreciated.

Proposed Solution

To address the problem, I restructured my code and came up with the following solution:

class EmailValidator {

    static isAvailableEmail(services: RegisterServices): (AbstractControl) => Promise<ValidationResult> {
        let g = (c: AbstractControl) => {
            return new Promise((resolve, reject) => {
                services.emailIsAvailable(antiForgeryToken(), c.value)
                    .then(result => {
                        // Verification of the result is necessary.
                        resolve({ "emailtaken": true })
                    },
                    error => {
                        // Should server errors be communicated? Probably not.
                        resolve({ "servererror": true })
                    });
            });
        };

        return g;
    }
}

I made adjustments to its usage as well:

...
this.registerForm = fb.group({
    email: ['', Validators.required,
        EmailValidator.isAvailableEmail(this._registerService)],
    password: ['', Validators.compose([Validators.required, Validators.minLength(8)])],
    phoneNumber: ['', Validators.required],
    country: ['', Validators.required]
    });
...

This modification now functions correctly.

Answer №3

The issue you are experiencing arises from passing the value of isAvailable, which is a function, without executing it. Instead, you are simply passing a reference to the function.

To resolve this problem, one approach is highlighted in @Thilo's response

Another solution involves assigning isAvailable to a lambda expression rather than a traditional function. Here's how:

class EmailValidator {

    constructor(private _registerServices: RegisterServices) { }

    isAvailable = (c: AbstractControl): Promise<ValidationResult> => {
        let q = new Promise((resolve, reject) => {
            this._registerServices.emailIsAvailable(antiForgeryToken(), c.value)
                .then(result => {
                    // It is crucial to verify the result.
                    resolve({ "emailtaken": true })
                },
                error => {
                    // Should you relay the server error? Probably not necessary.
                    resolve({ "servererror": true })
                });
        });

        return q;
    }
}

Answer №4

I propose writing it in a slightly alternative manner

class EmailChecker {

    constructor(private _registrationServices: RegistrationServices) { }

    checkAvailability(emailControl: AbstractControl): Promise<ValidationResult> {
        return this._registrationServices.validateEmail(antiForgeryToken(), emailControl.value)
            .then(res => {
                // Make sure to verify the outcome.
                return { "emailExists": true }
            })
 // concise .then(res => ({ "emailExists": true }))
            .catch(err => {
                // Should we inform about server issues? Probably not necessary.
                return { "serverIssue": true }
            });
 // concise .catch(error => ({ "serverIssue": true }))

        });

    }
}

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

incorrect implementation of react lifecycle phases

My Sharepoint Framework webpart includes a property side bar where I can choose a Sharepoint List, and it will display the list items from that list in an Office UI DetailsList Component. Although all REST calls are functioning properly during debugging, ...

Utilizing ngx-logger Dependency in Angular 6 for Efficient Unit Testing

Have you ever attempted to test classes in Angular that rely on ngx-logger as a dependency? I am looking for guidance or examples of how this can be achieved using testing frameworks such as Jasmine. It seems there are limited resources available on mock ...

Implementing Limited Results in Redis FT.SEARCH with TypeScript

Snippet of code: client.ft.SEARCH('license-index-json',"@\\$\\" + ".reservedForApplicationName:GSTest",{ LIMIT: { from: 0, to: 1 } }) Error message: An error occurred when trying t ...

Retrieve data from child routes within the parent component

In my Angular module routing structure, I have a parent component that contains child components represented as tab items. Here is the routing setup: { path: "teacher/:id", component: TeacherTabcontrolComponent, children: [ { path: & ...

Tips on accessing validator errors in Angular

Is there a way to extract the value from the 'minLength' validator error in order to use it in a message? This is my current HTML setup: <div class="mt-2" *ngIf="ngControl.control.errors?.minlength"> {{ &ap ...

When the Angular Reactive form control does not show any errors, it is designated as ng-invalid

Currently, I am working on an (Angular 10) reactive form that includes multiple dynamically-created input components within an ngFor loop. Here is an example of one of these input components: <div [id]="this.getDivElementId()" class="text ...

Dynamically loading components within an Angular application

I am tasked with displaying different components at specific times by iterating through them. Below is an example of how I have attempted to achieve this. The components I can use are determined by the server. <ngb-tabset [activeId]="1"> ...

What is the best way to end a Google OAuth session using Firebase on an Ionic 2 application?

My Ionic 2 app integrates Google Authentication using Firebase. I have implemented a logout button within the app that calls the Firebase unauth() method. However, this only disconnects the Firebase reference and does not terminate the Google OAuth session ...

A guide to accessing parent attributes in Vue3 using typescript

Within my child component, I am facing an issue where I need to access the parent object but the commented lines are not functioning as expected. The structure of AccordionState is defined below: export type AccordionKeys = | "open" | "disa ...

Deploying an Angular application on AWS EC2 without using nginx as a reverse proxy

Our team has been tackling the challenge of hosting an Angular application on AWS. A question has emerged: can we deploy the Angular application without relying on nginx? This inquiry arose when we successfully deployed a node.js application without any ...

How to simulate a particular class from a node package using Jest mocks

In my project, I'm looking to specifically mock the Socket class from the net node module. The documentation for this can be found here. Within my codebase, there is a class structured similar to the following... import { Socket } from 'net&apo ...

The function did not return a Promise or value as expected when using async and await

    I have been working on implementing this code structure for my cloud functions using httpRequest. It has worked seamlessly with those httpRequest functions in the past. However, I recently encountered an error when trying to use it with the OnWrite ...

Transferring css to an external file within an angular 4 component by utilizing webpack

I encountered this specific error message: Error: Anticipated 'styles' to be a collection of strings. Despite the fact that I have clearly defined the styles as an array of strings: styleUrls: ['./app.component.css'] Can anyone pinp ...

The vertical scrolling feature seems to be malfunctioning within my angular 10 application

I'm having an issue with the scrollbar not working on this Angular 10 template, even after adding the CSS style overflow: auto; to the main container. Although I've included the overflow property in the main container "cont" as shown in the HTML ...

angular displaying incorrect values for counter

Hi there, I am new to using Angular and I'm currently facing an issue with increasing and decreasing product quantity on the cart page. The problem is that in my first index it works fine, but in the second index, the value starts with the first index ...

Finding a solution to the dilemma of which comes first, the chicken or the egg, when it comes to using `tsc

My folder structure consists of: dist/ src/ In the src directory, I have my .ts files and in dist, I keep my .js files. (My tsconfig.json file specifies "outDir":"dist" and includes 'src'). Please note that 'dist' is listed in my git ...

When creating a responsive datatable in Angular, be aware that the reference to "this.table

Here is the code from my datatable.component.ts: import { Component,AfterViewInit, OnDestroy,ElementRef, ViewChild, OnInit } from '@angular/core'; declare var $; import { Http, Response } from '@angular/http'; import { Subj ...

Differences Between Angular Module and Library

Exciting news - Angular has recently launched version 6 with a new CLI feature that allows you to generate libraries, which they are calling a "highly anticipated feature". From a business standpoint, I am left pondering the following questions: What is ...

Angular 5 - Keeping track of variable updates

I've searched various topics on this issue, but none seem to address my specific problem. I need a way to detect changes in the properties of a component without having to convert the variable into an array or iterable. I tried using Subject, but coul ...

Creating TypeScript domain objects from JSON data received from a server within an Angular app

I am facing a common challenge in Angular / Typescript / JavaScript. I have created a simple class with fields and methods: class Rectangle { width: number; height: number; area(): number { return this.width * this.height; } } Next, I have a ...