[ngx-formly] Implement cross-cutting functionality with Angular Formly Extensions

Assume we want to add a data-cy attribute to all of our form controls. We need this as a hook to later be able to easily grab our input fields from within our Cypress integration tests. Of course we could manually add these data- attributes to each of our formly field configuration. But there's a much more elegant approach: extensions. In this lesson we're going to see how they work.

customs/data-cy.extension.ts:

import { FormlyExtension, FormlyFieldConfig } from '@ngx-formly/core';

export const dataCyExtension: FormlyExtension = {
  prePopulate(field: FormlyFieldConfig) {
    field.templateOptions = {
      ...(field.templateOptions || {}),
      attributes: {
        'data-cy': field.key,
      },
    };
  },
};

app.modules.ts:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { ReactiveFormsModule, FormControl, ValidationErrors } from '@angular/forms';
import { FormlyModule, FormlyFieldConfig } from '@ngx-formly/core';
import { FormlyMaterialModule } from '@ngx-formly/material';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgSelectModule } from '@ng-select/ng-select';

import { SharedModule } from './shared/shared.module';
import { NgSelectFormlyComponent } from './customs/ng-select.type';
import { dataCyExtension } from './customs/data-cy.extension';

// global min error message, you can override by validation.messages.min in field
export function minValidationMessage(err, field: FormlyFieldConfig) {
  return `Please provide a value bigger than ${err.min}. You provided ${err.actual}`;
}

export function ipValidationMessage(err, field: FormlyFieldConfig) {
  return `"${field.formControl.value}" is not a valid IP address`;
}

export function IpValidator(control: FormControl): ValidationErrors {
  return !control.value || /(\d{1,3}\.){3}\d{1,3}/.test(control.value) ? null : { ip: true };
}

@NgModule({
  declarations: [AppComponent, NgSelectFormlyComponent],
  imports: [
    BrowserModule,
    SharedModule,
    NgSelectModule,
    ReactiveFormsModule,
    FormlyModule.forRoot({
      validators: [
        {
          name: 'ip',
          validation: IpValidator,
        },
      ],
      validationMessages: [
        {
          name: 'required',
          message: 'This field is required',
        },
        {
          name: 'min',
          message: minValidationMessage,
        },
        {
          name: 'ip',
          message: ipValidationMessage,
        },
      ],
      types: [
        {
          name: 'my-autocomplete',
          component: NgSelectFormlyComponent,
        },
      ],
      extensions: [
        {
          name: 'data-cy-extension',
          extension: dataCyExtension,
        },
      ],
    }),
    FormlyMaterialModule,
    BrowserAnimationsModule,
  ],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}

Then all the fileds will get 'data-cy' attr

猜你喜欢

转载自www.cnblogs.com/Answer1215/p/12173129.html