0

When trying this example from the ngx-formly library, the message that comes from the async validation is not displaying under the field as exprected

https://formly.dev/docs/examples/validation/unique-value-async-validation/

When reducing the timeout in the async validator expression, I see that the async validator is called instantly, but the message: 'This username is already taken.' is not displayed under the field !

Here is the code from the stackblitz link:

Template

<b>Existing usernames</b>
<ul>
  <li *ngFor="let u of existingUsers">{{ u }}</li>
</ul>

<form [formGroup]="form" (ngSubmit)="submit()">
  <formly-form [model]="model" [fields]="fields" [options]="options" [form]="form"></formly-form>
  <button type="submit" class="btn btn-primary submit-button">Submit</button>
</form>

component class

import { Component } from '@angular/core';
import { FormGroup, AbstractControl } from '@angular/forms';
import { FormlyFormOptions, FormlyFieldConfig } from '@ngx-formly/core';
import { of } from 'rxjs';

@Component({
  selector: 'formly-app-example',
  templateUrl: './app.component.html',
})
export class AppComponent {
  form = new FormGroup({});
  model: any = {};
  options: FormlyFormOptions = {};

  existingUsers = ['user1', 'user2', 'user3'];

  fields: FormlyFieldConfig[] = [
    {
      key: 'username1',
      type: 'input',
      props: {
        label: 'Username (validated using `Promise`)',
        placeholder: 'Username',
        required: true,
      },
      asyncValidators: {
        uniqueUsername: {
          expression: (control: AbstractControl) => {
            return new Promise((resolve) => {
              setTimeout(() => {
                resolve(this.existingUsers.indexOf(control.value) === -1);
              }, 0);
            });
          },
          message: 'This username is already taken.',
        },
      },
    },
    {
      key: 'username2',
      type: 'input',
      props: {
        label: 'Username (validated using `Observable`)',
        placeholder: 'Username',
        required: true,
      },
      asyncValidators: {
        uniqueUsername: {
          expression: (control: AbstractControl) => {
            return of(this.existingUsers.indexOf(control.value) === -1);
          },
          message: 'This username is already taken.',
        },
      },
    },
  ];

  submit() {
    if (this.form.valid) {
      alert(JSON.stringify(this.model));
    }
  }
}

module configuration:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';
import { FormlyModule } from '@ngx-formly/core';
import { FormlyBootstrapModule } from '@ngx-formly/bootstrap';
import { AppComponent } from './app.component';

@NgModule({
  imports: [
    BrowserModule,
    ReactiveFormsModule,
    FormlyBootstrapModule,
    FormlyModule.forRoot({
      validationMessages: [{ name: 'required', message: 'This field is required' }],
    }),
  ],
  bootstrap: [AppComponent],
  declarations: [AppComponent],
})
export class AppModule {}

Stackblitz link: https://stackblitz.com/edit/angular-f3fx7j?file=src%2Fapp%2Fapp.component.ts,src%2Fapp%2Fapp.module.ts

Question: is there any way to display the async validation message whenever the validation is not working.

Thanks

1 Answer 1

-1

Step 01 In order to display this message to the user, you'll need to subscribe to the observable and set the error message on the form control.

import { FormControl } from '@angular/forms';
import { Observable } from 'rxjs';
export function asyncValidator(control: FormControl): Observable<any> {
  return new Observable(observer => {
    // simulate an asynchronous validation
    setTimeout(() => {
      if (control.value === 'test') {
        observer.next({ asyncValidation: 'Validation failed' });
      } else {
        observer.next(null);
      }
      observer.complete();
    }, 1000);
  });
}

Step 2 To use this validator with ngx-formly, you can define it as part of the field configuration

{
  key: 'test',
  type: 'input',
  templateOptions: {
    label: 'Test',
  },
  validators: {
    async: asyncValidator,
  },
  validation: {
    messages: {
      asyncValidation: 'Async validation failed',
    },
  },
},
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your answer. Can you provide a working Stackblitz for this ? or fork the provided one to demo this ?
Can you update your answer with a demo, to show that it works ?, it's not working for me.

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.