0

I have an <input> where the user enter a value that is supposed to be unique in database. I want to check dynamically in the front-end if that value is unique or not.

I want also to display an error message if the value is already stored in database.

1 Answer 1

1

You can use a custom async validator to do that. Let's say you want to check that the name is unique. First, create a new file for the async validator :

@Injectable({ providedIn: 'root' })
export class NameValidator {

    constructor(private nameService: NameService) { }

    CheckNameValidator(): AsyncValidatorFn {
        return (control: AbstractControl): Observable<{ [key: string]: boolean } | null> => {
            return this.nameService.nameExists(control.value)
                .pipe(
                    map(valueExists => {
                        if (valueExists) {
                            return { nameExists: true };
                        }
                        return null;
                    }
                    )
                )
        }
    }

The validator is a service where you import the service nameService where you can call your api. The api must return if the value is present or not. Then, in the controller :


export class MainComponent implements OnInit {

  constructor(
    private fb: FormBuilder,
    private nameValidator: NameValidator 
    ) {}

public formGroup: FormGroup;

ngOnInit(): void { 
  
    this.formGroup = this.fb.group({
      name: ['', [Validators.required, Validators.minLength(3)], [this.nameValidator.CheckNameValidator()]]
    }, {updateOn: 'blur'});
  }

When you build your formgroup, each form control can hold a value, an array of validators, and an array of async validators. That's where i put the call to the asyn validator service.

Notice the {updateOn: 'blur'}, if you do not write this, the update to check the validators is on change, so you make way too many api calls. With onBlur the api call is done onblur => performance gain.

If you use angular material, your view should look something like this :

<ng-container [formGroup]="formGroup">
    <mat-form-field class="field-full-width">
        <input matInput placeholder="Name" formControlName="name">
        <mat-error *ngIf="formGroup.controls['name'].errors?.nameExists">This name is already in use</mat-error>
    </mat-form-field>
</ng-container>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.