CAlex
CAlex

Reputation: 1140

RegEx for not matching multiple exact strings

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

Answers (2)

Pushpesh Kumar Rajwanshi
Pushpesh Kumar Rajwanshi

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)$).+$

Regex Demo

Upvotes: 1

Akxe
Akxe

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

Related Questions