Developing asynchronous custom validation in Angular 2 using a Web API request

Looking to implement an async custom validator for checking the availability of a username in a signup form? I've set up a service class that interacts with the Web API (as shown below) to perform this check.

In addition, I've developed an async custom validator that is supposed to interface with the service and carry out the validation process. However, I'm encountering difficulties understanding how to inject the service into the validator. The service itself is injected with Http.

If anyone has insights on how to execute this validation correctly, your input would be much appreciated.

-Alan-

Custom Validator

export class UserNameValidators {
    static shouldBeUnique(control: FormControl) {
           ....
           //Need to call the Signup service here
        }
    }

Service

@Injectable()
export class SignUpService
{
        constructor(private http: Http) {

          }
shouldBeUnique(username: string): Observable<boolean> {
        let headers = new Headers();
        headers.append('Content-Type', 'application/x-www-form-urlencoded');
        let options = new RequestOptions({ headers: headers });

               return this.http.post('localhost/authentication/api/accounts/user/' + username, '', options)
            .map((response: Response) => {
                let result = response.toString();
                if (result === 'true')
                    return true

                return false;
            })
            .catch((error: any) => {
                if (error.status === 400) {
                    var cleandata = error._body
                        .replace(/\\n/g, "\\n")
                        .replace(/\\'/g, "\\'")
                        .replace(/\\"/g, '\\"')
                        .replace(/\\&/g, "\\&")
                        .replace(/\\r/g, "\\r")
                        .replace(/\\t/g, "\\t")
                        .replace(/\\b/g, "\\b")
                        .replace(/\\f/g, "\\f");

                    cleandata = cleandata.replace(/[\u0000-\u001F]+/g, "");

                    return Observable.throw(new Error("Unknown Error"));
                }

            });
    }
}

Update

App.Module

@NgModule({
    imports     : [BrowserModule, HomeModule, SignupModule,signupRouting, routing],
    declarations: [AppComponent],
    providers   : [AuthService, AuthGuard, SignupService],
    bootstrap   : [AppComponent]
})

Custom Validator

export class UserNameValidators {

    constructor(private service: SignupService) { }

    shouldBeUnique(control: FormControl) {
        return new Promise((resolve, reject) => {

            this.service.shouldBeUnique(control.value).subscribe(
                data => {
                    if (data.length == 0 || data.length == 1) {
                        resolve(null);
                    } else {
                        resolve({ shouldBeUnique: true });
                    }
                },
                err => {
                    resolve({ shouldBeUnique: true });
                }
            )
        });

    }
}

Signup.component

export class SignupComponent implements OnInit {
    form: FormGroup;
    signedUp: boolean = false;
    error = '';

    constructor(private fb: FormBuilder, private router: Router, private signupService: SignupService) { }

    ngOnInit() {
        this.form = this.fb.group({
            firstname: ['', Validators.required],
            lastname: ['', Validators.required],
            username: ['', Validators.compose([Validators.required, UserNameValidators.notValidEmail]), new UserNameValidators(this.signupService).shouldBeUnique],

            password: ['', Validators.compose([Validators.required, UserNameValidators.cannotContainSpace])],
            confirmpassword: ['', Validators.compose([Validators.required, UserNameValidators.cannotContainSpace])]
        }, { validator: this.matchingPasswords('password', 'confirmpassword') });
    }
}

Answer №1

Currently, I'm facing a challenge in grasping the concept of injecting the service into the validator

Do you mean to ask this question?

To inject your service into the validator, you must first register it as a provider in your app.module:

@NgModule({ 
    // imports, etc
    providers: [
    appRoutingProviders,
    SignUpService]})

Make sure to use @Injectable() to decorate your service:

@Injectable()
export class SignUpService {
// code for your service...

In your validator, include a constructor that accepts SignUpService as a parameter:

constructor(private signUpService: SignUpService)
{

}

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

Verify the specific type conditions of a key value in a mapped type

I am attempting to achieve the following: If the actions property exists, and there are callbacks within the actions properties that return a string, then return X or Y. The above code is expressed as: // type MappedType<T> = { // [K in keyof T]: ...

Is it necessary to utilize RequestHandler every time I create an Endpoint in Sveltekit?

As I work on creating a Todo website, I came across a video tutorial about building a Svelte fullstack app. The teacher in the video demonstrated the use of RequestHandler to create an endpoint. However, in the SvelteKit documentation, it recommends using ...

Combining and forming a distinctive case-sensitive array in JavaScript

Explaining a complex scenario, I have one object or array and one array. My goal is to compare selectedmodel values with mappedmodels. If the value (case insensitive) matches any key in the object, I need to fetch all associated values and push them into t ...

Troubleshooting Angular 2: Instances of Classes Not Being Updated When Retrieving Parameters

I am facing an issue with the following code snippet: testFunction() { let params = <any>{}; if (this.searchTerm) { params.search = this.searchTerm; } // change the URL this.router.navigate(['job-search'], {q ...

Tips for compacting JSON in Typescript

I have encountered a challenge in my coding where we are dealing with quite large data objects. I am exploring the possibility of compressing these data objects to reduce payload size. For instance, if our input json size is 2 MB, can it be compressed to a ...

Retrieving latitude and longitude from place id in an Angular Google Maps component

Currently utilizing the google-maps component to extract latitude and longitude from Google Maps prediction data. Additionally, I have integrated a search bar using google-maps component. I have successfully implemented a search bar with ngx-google-places ...

Automatically generated error notifications for Express-Validator

I am looking to implement an Express API and incorporate request input validation using express-validator. Here is my current validation middleware: protected validate = async (request: Request, response: Response, next: NextFunction): Promise<void> ...

Blend Mode / Vue CLI / Remote server routing

I'm looking for a solution to set up a proxy in an AngularCLI/Webpack environment. The main goal is to forward requests from http://localhost:4200/rest to https://someserver.com/somepath/rest. One challenge is that the endpoint is using HTTPS instead ...

Angular 12's BehaviorSubject should have been empty object array, but it unexpectedly returns undefined

Exploring different scenarios with a livesearch functionality: No user input (observable = undefined) No results found (observable = empty array) Results found (observable = non-empty array) The issue lies in how my behavior subject interprets an empty a ...

Angular 10 is not displaying images despite receiving the image path from an API

Despite my API returning the image path for the product, my Angular application is not displaying the image. https://i.sstatic.net/PhD1s.png HTML Code <ng-container *ngFor="let prod of productData"> <div class="row p-2 b ...

What steps can be taken to implement jQuery within an Angular 15 npm package?

In my development process, I often create my own npm packages using Angular and Typescript. One of the packages I am currently working on is a PDF viewer service, which includes a file named pdf-viewer.service.ts with the following code: import { Behavior ...

Utilizing template logic that draws from a fusion of two distinct texts

Looking to display two different texts depending on a boolean value. Here is what I attempted: <div name="health-plans" *ngIf="!flagon"> Test<br />data </div> <div name="health-plans&quo ...

What is the process for including a version number in npm pack?

I've been working on deploying TeamCity with NPM pack, and I've noticed that it's packaging everything up as filename-0.0.0.tgz. So, I decided to switch to the command line to troubleshoot before running it through TC. When I run npm pack i ...

``The issue with the functionality of Angular animation stagger not performing correctly

I'm currently facing an issue with the new animation features in Angular 4.2, specifically the query and stagger functionalities. Anticipated behavior: I expect that when I click on the Toggle button, every element with the attribute [animate-bar] wi ...

What is the best way to retrieve the action parameter in an NgRx effect?

Is it possible to send an action with a parameter and replace the value (9) with (block.id)? this.store.dispatch(RegistryActions.LoadRegistryLayersAction(this.block)); How can I access this parameter in the effect? loadRegistriesLayers$: Observable<Act ...

Embedding in webpack compilation

My current setup involves using webpack 2.4.2 for a Typescript-based AngularJS 1.6 application. Whenever I make modifications to files like .ts, .js, and .less, webpack automatically scans for lint errors and notifies me about them. Although I'm unsu ...

Step-by-step guide to creating a reverse index in ngFor with Angular

I am currently using the most up-to-date version of Angular and have an array named "myarray" containing 3 objects. My goal is to have div elements structured like this: <div id="num2"> <div id="num1"> <div id="num0"> Typically, I woul ...

What is the best way to attach a button to a mat-drawer?

I am facing an issue with aligning a button to a mat drawer located to the right of the screen to ensure a clear overall design. Check out this example How can I achieve this alignment? My current approach involves placing the button inside the drawer an ...

The element 'blockquote-reverse' in Angular2 is unrecognized and not supported

While attempting to utilize an element tag provided by Bootstrap 3.3.6 in my component view, I encountered an error stating that it is an unknown element. Any suggestions on how to resolve this issue? The error message reads 'blockquote-reverse&apos ...

The functionality of the Angular Password Strength Extension Color appears to be malfunctioning

I recently integrated the @angular-material-extensions/password-strength extension into my project. I followed the showcase example provided on their website at However, I encountered an issue where the primary color was not displaying correctly. Only the ...