Reputation: 1140
I am looking to limit what a user can input into a field based on previous entries that already exist.
For example, a user has entered these values into the database already:
["typescript", "C#", "python"]
When they type one of these already existing values into the input field EXACTLY, I want the validator message to appear.
I have this negative look ahead Regex from another answer I found:
^(?!.*(typescript|C#|python)).*$
but it will fail validation if one of those words appears anywhere in the input string (for example: "pythons" would fail). I just want it to fail if one of those words appear exactly in the input.
EDIT
I ended up using the custom validator solution provided below. The regex solution below did also work. As discussed, validators are the correct solution for this particular issue.
Upvotes: 1
Views: 495
Reputation: 18357
As you are preferring to look for a regex solution, you can use this regex to reject matches when it is exactly any one of these,
typescript
C#
python
The negative look ahead you wanted to use needs to be written like this,
^(?!(?:typescript|C#|python)$).+$
Upvotes: 1
Reputation: 11575
You should not use regexp as it is quite an overkill, use custom validator
export function usedNames(validNames: string[]): ValidatorFn {
return (control: AbstractControl): {[key: string]: any} | null => {
if (validNames.includes(control.value)) {
return null;
} else {
return { usedNames: {value: control.value} };
}
};
}
Usage (reactive form):
new FormGroup({
'language': new FormControl(this.hero.name, [
Validators.required,
usedNames(['typescript', 'C#', 'python']) // <-- Here's how you pass in the custom validator.
]),
// ... (other inputs)
});
Usage (template form):
@Directive({
selector: '[appUsedNames]',
providers: [{provide: NG_VALIDATORS, useExisting: UsedNamesDirective, multi: true}]
})
export class UsedNamesDirective implements Validator {
@Input('appUsedNames') usedNames: string;
validate(control: AbstractControl): {[key: string]: any} | null {
return this.usedNames ? usedNames(this.usedNames)(control) : null;
}
}
Also, you should think about making it select
instead of input
or add list
& <datalist>
to the input so that the user knows what he can type...
Upvotes: 1