3
votes

I have written a custom validation directive like that:

const DURATION_VALIDATOR = new Provider(
    NG_VALIDATORS,
    {useExisting: forwardRef(() => DurationDirective), multi: true}
);


@Directive({
    selector: '[ngModel][duration], [formControl][duration]',
    providers: [{
        provide: NG_VALIDATORS,
        useExisting: forwardRef(() => DurationDirective),
        multi: true }]
})
export class DurationDirective  implements Validator{
    constructor(public model:NgModel){
        console.error('init')
    }
    validate(c:FormControl) {
        console.error('validate')
        return {'err...':'err...'};
    }
}

My Html looks like this:

<input 
    type="text"
    [(ngModel)]="preparation.duration"
    duration 
    required
>

My problem is that while the validator is initialized, i.e. 'init' is logged to console, the validate function is never called, i.e. 'validate' is never logged to the console, when typing into the input field. Since the validator is initialized, I assume that I "wired" up everything correctly. So what is missing?

3

3 Answers

0
votes

My best bet is that you haven't bootstraped Angular with regards to forms:

import { App } from './app';
import { disableDeprecatedForms, provideForms } from '@angular/forms';

bootstrap(App, [
    // these are crucial
    disableDeprecatedForms(),
    provideForms()
  ]);

You can see this plunk - it does output "validate" to the console.

0
votes

I forked and improved @batesiiic 's plunk: https://plnkr.co/edit/Vokcid?p=preview

validate(c:FormControl) {
    console.error('called validate()')
    return parseInt(c.value) < 10 ? null : {
      duration: {message: 'Please enter a number < 10'}
    };
}

The validate() method must return null if the input is valid, otherwise, it returns an object { key: value, ... } where key is the type of error and value can be anything you can use in your template to generate an error message.

The template also contains a div to display the error message if the input is not valid.

0
votes

Instead of writing the custom validator function as class/component/Directive method, Writing Custom validator outside the component/Directive should work.

validate(c:FormControl) {
    console.error('validate')
    return {'err...':'err...'};
}

@Directive({
    selector: '[ngModel][duration], [formControl][duration]',
    providers: [{
        provide: NG_VALIDATORS,
        useExisting: forwardRef(() => DurationDirective),
        multi: true }]
})
export class DurationDirective  implements Validator{
    constructor(public model:NgModel){
        console.error('init')
    }

}