Open Closed

Angular Reactive Forms Async Validators #454


User avatar
0
jeboersema created

Is it possible to use the AsyncValidator capabilities of Angular's ReactiveForms with ABP.IO?

I managed to build a custom validator that get's executed but I am unable to have the error message displayed in the red box when the control fails the validation.

Any example would be helpfull.

  • ABP Framework version: v3.1.2
  • UI type: Angular 10
  • Tiered (MVC) or Identity Server Seperated (Angular): no
  • Exception message and stack trace: None
  • Steps to reproduce the issue: Create a ReactiveForm and add a custom AsyncValidator to one of the inputs.

Below is my validator function:

validateCodeExists({value}: AbstractControl): Observable<ValidationErrors | null> {
    const dto: CountryExistsDto = { id: this.selectedCountry.id, code: value};
    console.log("Code Exists:", dto);
    return this.countryService.exists(dto)
        .pipe(debounceTime(500), map((codeExists: boolean) => {
            if (codeExists) {
              return {
                exists: true,
              };
            }
            return null;
        }));
    }

**The HTML for the control looks as follows: **

<div class="form-group">
    <label for="code">{{ '::Code' | abpLocalization }}</label><span> * </span>
    <input type="text" id="code" class="form-control" formControlName="code" placeholder="ISO 3166-1 Alpha-2 Country Code" />
    <span *ngIf="form.get('code').errors?.exists">Country code already exists!</span>
</div>

The result looks as follows


2 Answer(s)
  • User Avatar
    0
    armanozak created

    Hi,

    Sorry for the missing documentation on the matter. We are actively trying to improve our documentation and this has been opened as an issue now.

    Please do not put any additional <span> elements to your HTML. The validation will happen automatically. Instead, put the provider below to the app.module.ts file.

    import { VALIDATION_BLUEPRINTS } from '@ngx-validate/core';
    
    @NgModule({
      // rest of the module metadata
    
      providers: [
        // other providers
    
        {
          provide: VALIDATION_BLUEPRINTS,
          useValue: {
            exists: 'Country code already exists!',
          },
        },
      ],
    })
    export class AppModule {}
    

    You may use a localization resource and key instead if you want to localize the message.

    Please let me know if this resolves the issue for you.

    Have a nice day.

  • User Avatar
    0
    jeboersema created

    Hi,

    Your solution has worked as expected.

    I have however implimented a custom provider in a seperate file in order to not have a long list of validation messages in the app.module.ts file.

    So in my app.module.ts I do the following:

    import { VALIDATION_MESSAGE_PROVIDER } from "./shared/validationMessage.provider";
    
    ...
    
      providers: [APP_ROUTE_PROVIDER, VALIDATION_MESSAGE_PROVIDER],
      bootstrap: [AppComponent],
    })
    export class AppModule {}
    

    Then I have implimented the VALIDATION_BLUEPRINTS in the following seperate file:

    import { VALIDATION_BLUEPRINTS } from '@ngx-validate/core';
    import { LocalizationService } from '@abp/ng.core';
    import { Injectable } from '@angular/core';
    
    @Injectable()
    export class ValidationMessageService {
      constructor(public localizationService: LocalizationService) {}
    
      exists = this.localizationService.instant("WealthMaster::Validation.Country.Exists");
    }
    
    export const VALIDATION_MESSAGE_PROVIDER = [
      {
        provide: VALIDATION_BLUEPRINTS,
        useClass: ValidationMessageService
      },
    ];
    

    And the result looks as follows:

    Thankyou for your assitance

Made with ❤️ on ABP v8.2.0-preview Updated on March 25, 2024, 15:11