0

I am trying to create a validator for one of the fields in my form. This validator is created in a service, however, to create it I must make a get request that returns the value with which my validator must match, but since the server's response does not occur instantly when returning the value, it is always returned undefined. How can I stop the execution of the code until I get a response from the service?

constructor(private formBuilder: FormBuilder, private validators : ValidatorsService) 
{
     this.form = this.formBuilder.group({
         max_range: [null, this.validators.getMaxRangeValidators()]
         }
     )
}

function in service ValidatorsService

public getMaxRangeValidators(): any[] {
    let validators = [];
    this.httpClient.get<Range>(this.url).suscribe(
        (data)=>{
            validators = [Validators.maxLength(data.maxLength)];
        }
    )
    return validators;
}

1 Answer 1

3

You will need to implement async validator for your use case. Async validators lets you perform async operations (in your case, API calls).

An example, the below validator makes an API call to search for users and returns error if the user exists:

userValidator(): AsyncValidatorFn {
    return (control: AbstractControl): Observable<{ [key: string]: any } | null> => {
      return this.searchUser(control.value)
        .pipe(
          map(res => {
            // if username is already taken
            if (res.length) {
              // return error
              return { 'userNameExists': true };
            }
          })
        );
    };

For your use case:

public getMaxRangeValidators(): AsyncValidatorFn {
   return (control: AbstractControl): Observable<{ [key: string]: any } | null> => {
     return this.httpClient.get<Range>(this.url).pipe(map(res => {
        if(control.value > res.maxLength) {
          return {
            'rangeError' : true,
            'errorMessage': 'Length can't exceed ' + res.maxLength
          }
        }
     }));
    }
  }

And then in your template you can check for rangeError for the control and use the errorMessage property to display the error.

More details: https://angular.io/api/forms/AsyncValidator

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you very much for your answer, but in case you need the value of the range also to assign in an error message and in a placeholder, you would have to make a separate call to the service. Is there a way other than asynchronous to do this?
for error message you can use the object returned from validator. Check updated answer. For placeholder you need to have that information in advance.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.