I have a question regarding an input element type number that I want to validate in a template-driven form:
As the first goal, it should accept only positive integer values. For this, I have created a validator function that gets the input value, evaluates a regex expression, and returns errors if it fails. I wrapped it within a directive and used it with the input element in the template. So far, all is good and it works perfectly.
As the second goal, it should accept a NULL value. For example, since the field is not mandatory, the end user could leave it empty (NULL) and then submit the form. At first, I thought that extending the validator with a condition for when the element is NULL will do the job, and it did. But the problem comes when typing values like -2 or 2.3 or 2.3-... in those cases the validator gets also the input value NULL so I cannot distinguish when the user leaves the input field empty (NULL) or when he's typing an invalid value. I guess the NULL comes from a previous built-in validator running. Is there a way to get access to the actual value of the input field?
this is how the code pretty much looks in the template:
<input
name="testInputField"
id="xyz"
type="number"
step="1"
min="0"
[(ngModel)]="controllerVariable"
myDirective/>
...and this is how the directive looks like
import { Directive } from '@angular/core';
import { NG_VALIDATORS, AbstractControl, Validator, ValidationErrors, ValidatorFn } from '@angular/forms';
export function myValidator(): ValidatorFn {
const regExp = /^\d+$/;
return (control: AbstractControl): ValidationErrors | null => {
return control.value === null
? null
: regExp.test(control.value)
? null
: { myValidator: { valid: false } };
}
}
@Directive({
selector: '[myDirective]',
providers: [{
provide: NG_VALIDATORS,
useExisting: MyDirective,
multi: true,
}],
})
export class MyDirective implements Validator {
public validate(control: AbstractControl): ValidationErrors | null {
return myValidator()(control);
}
};
Any hints or ideas to refactor my solution are highly appreciated. Thanks
type="number"to an <input> field, I'm actually shocked this is the way it works. One option is clearly to not usetype="number"and instead usetype="text". Assuming this is not a valid option, I would consider passing in the value from the <input> DOM element itself, e.g. using @ViewChild() andviewChildVariable.nativeElement.target.value.NULLin thenativeElement. After having a look at Mozilla I come to the conclusion that if I want to acceptNULLas a valid value,<input>type "number" won't work. I believe choosing the type "text" will do the job