Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inject a service in a custom validator in Angular2

I try to use a service in a custom validator to check if a username already exists.

import {Component} from 'angular2/core';
import {
    Control,
    ControlGroup,
    FormBuilder
} from "angular2/common";
import {CharacterService} from "./character-service";

@Component({
    selector: 'register-character-form',
    template: `
        <h2 class="ui header">A new adventurer is coming...</h2>
        <form (ngSubmit)="register()" [ngFormModel]="characterForm" class="ui form">
            <div class="field">
                <label>Nom</label>
                <input ngControl="name">
            </div>
            <button type="submit" class="ui button">Enter in the adventure</button>
        </form>
    `,
    providers: [CharacterService]
})
export class RegisterCharacterFormCmp {
    characterForm: ControlGroup;
    name: Control;

    constructor(private _characterService: CharacterService, fb: FormBuilder) {
        this.name = fb.control('', this.characterNameValidator);

        this.characterForm = fb.group({
            name: this.name
        });
    }

    register(): void {
        //TODO: To implement
    }

    // Not works, this binds the control
    characterNameValidator(control: Control) {
        return this._characterService.isCharacterNameAlreadyExists(control.value) ? {nameCharacterAlreadyExistsError: true} : null;
    }
}

It doesn't work. In the characterNameValidator, 'this' references the control and not my class. The service is undefined. How can I use my service in the validator ?

More globally, how can I pass arguments in a custom validator ?

like image 845
Kelem Avatar asked Feb 06 '16 22:02

Kelem


People also ask

How do I use custom validator?

in order to implement a custom validation directive, we need to implement the Validator interface, which only has the validate method. the validate method is going to call the validation creation function, and pass the control reference (the password control in this case) to the validator.

What must be returned from a custom validator function?

Custom Model-Driven Validators Validators at their core are just functions, they take as input a FormControl instance and returns either null if it's valid or an error object if it's not.

How do I add validation in template-driven form?

To add validation to a template-driven form, you add the same validation attributes as you would with native HTML form validation. Angular uses directives to match these attributes with validator functions in the framework.

Is it possible to define validators in form builder?

FormBuilder allows us to explicitly declare forms in our components. This allows us to also explicitly list each form control's validators.


2 Answers

You need to control what this means in your validation. You can do so with bind

this.name = fb.control('', this.characterNameValidator.bind(this));

Everything else should work as expected then.

like image 158
SnareChops Avatar answered Sep 22 '22 14:09

SnareChops


You can use an arrow function to keep the context the same.

this.name = fb.control('', (control: Control) => this.characterNameValidator(control));
like image 21
toskv Avatar answered Sep 21 '22 14:09

toskv