Skip to main content
Version: 8.3

Implement a custom validator using remote module

Level: advanced

To implement the example:

  1. Create an Angular project. Read more >>>
  2. Install npm packages. Read more >>>
  3. Create a custom validator. Read more >>>
  4. Add the custom validator to the Freedom UI page. Read more >>>
Example

Add a custom validator to the custom request page. The validator checks whether the Name field starts with the "REQ-" prefix. If the prefix is omitted, display the 'Add "REQ-" prefix' message. Implement the validator using a remote module created in the Angular framework.

Example implementation in Creatio 8.3.4 and later​

1. Create an Angular project​

To create an Angular project, follow the instructions: Create an Angular project.

For this example:

  • <%projectName%> macro is set to "sdk_custom_validator."
  • <%vendorPrefix%> macro is set to "usr."

As a result, an Angular project to develop a custom validator using a remote module will be added.

2. Install npm packages​

To install npm packages, follow the instructions: Install npm packages.

As a result, required npm packages are installed.

3. Create a custom validator​

  1. Ensure the project includes the "AGENTS.md" file. Instructions: Create a custom Freedom UI component (step 1).

  2. Run the ng g class features/runtime/validators/verify-request-name.validator command in the Visual Studio Code terminal to create an Angular class in the project. This adds the VerifyRequestNameValidator class files to the "src/app/features/runtime/validators" project directory.

  3. Implement the validator.

    1. Open the "verify-request-name.validator.ts" file.
    2. Flag the VerifyRequestNameValidator class using the @CrtValidator decorator.
    3. Extend the BaseValidator class from the @creatio-devkit/common library.
    4. Override the async field.
    5. Override the validate() method that validates data in the field.
    6. Import the required functionality from the libraries into the class.
    7. Save the file.
    "verify-request-name.validator.ts" file
    /* Import the required functionality from the libraries. */
    import {
    BaseValidator,
    CrtControlState,
    CrtValidationErrors,
    CrtValidator,
    ValidatorParametersValues
    } from '@creatio-devkit/common';

    export const REQUEST_NAME_PREFIX = new InjectionToken<string>('REQUEST_NAME_PREFIX');

    /* Add the CrtValidator decorator to the VerifyRequestNameValidator class. */
    @CrtValidator({
    type: 'usr.VerifyRequestNameValidator',
    })

    export class VerifyRequestNameValidator extends BaseValidator {

    /* Inject the dependency using the @CrtInject decorator. */
    constructor(@CrtInject(REQUEST_NAME_PREFIX) private _prefix: string) {
    super();
    }

    protected override async = false;

    public validate(
    control: CrtControlState,
    params?: ValidatorParametersValues
    ): CrtValidationErrors | null {
    const value = control.value as string;
    const maxLength = (params as { maxLength?: number } | undefined)?.maxLength;
    if (
    value &&
    (!value.startsWith(this._prefix) ||
    (typeof maxLength === 'number' && value.length > maxLength))
    ) {
    return {
    error: {
    message: 'Add "REQ-" prefix',
    },
    };
    }
    return null;
    }
    }
  4. Inject dependencies.

    1. Open the "verify-request-name.validator.ts" file.
    2. Create the REQUEST_NAME_PREFIX injection token using the InjectionToken class. Use the token to work with Angular DI (dependency injection).
    3. Inject the dependency into the constructor of the VerifyRequestNameValidator class using the @CrtInject decorator.
    4. Import the required functionality from the libraries into the class.
    5. Save the file.
    "verify-request-name.validator.ts" file
    /* Import the required functionality from the libraries. */
    import { InjectionToken } from "@angular/core";
    import { CrtInject } from "@creatio-devkit/common";

    /* The REQUEST_NAME_PREFIX token that works with Angular DI (dependency injection). */
    export const REQUEST_NAME_PREFIX =
    new InjectionToken<string>('REQUEST_NAME_PREFIX');

    export class VerifyRequestNameValidator extends BaseValidator {
    /* Inject the dependency using the @CrtInject decorator. */
    constructor(@CrtInject(REQUEST_NAME_PREFIX) private _prefix: string) {
    super();
    }

    }
  5. Register the VerifyRequestNameValidator validator and the REQUEST_NAME_PREFIX token. The template already contains the runtime feature activation and bootstrapCrtModule() call. Extend the existing runtime feature files to register the validator.

    1. Open the "runtime-feature.module.ts" file.

    2. Add the VerifyRequestNameValidator validator to the validators section in the @CrtModule decorator.

    3. Add the configuration object to the providers section in the @NgModule decorator.

      • Set the provide property to "REQUEST_NAME_PREFIX."
      • Set the useValue property to "REQ-."
      "runtime-feature.module.ts" file
      /* Import the required functionality from the libraries. */
      import { ApplicationRef, DoBootstrap, NgModule } from '@angular/core';
      import { BrowserModule } from '@angular/platform-browser';
      import { CrtModule } from '@creatio-devkit/common';

      import {
      REQUEST_NAME_PREFIX,
      VerifyRequestNameValidator
      } from './validators/verify-request-name.validator';

      @CrtModule({
      /* Specify that VerifyRequestNameValidator is a validator. */
      validators: [VerifyRequestNameValidator],
      })
      @NgModule({
      imports: [BrowserModule],
      providers: [
      {
      provide: REQUEST_NAME_PREFIX,
      useValue: 'REQ-',
      },
      ],
      })
      export class RuntimeFeatureModule implements DoBootstrap {
      ngDoBootstrap(_appRef: ApplicationRef): void {}
      }
    4. Open the "runtime.feature-definition.ts" file.

    5. Add the public type property of the validator to the discovery.validators section.

      "runtime.feature-definition.ts" file
      /* Import the required functionality from the libraries. */
      import type {
      RemoteDesignerDefinitionsLoadContext,
      RemoteFeatureDefinition
      } from '@creatio-devkit/common';

      /**
      * Root definition for the runtime feature.
      *
      * Describes the view elements this remote package contributes at runtime
      * and provides the entry points used to load designer metadata and activate
      * the feature.
      */
      export const runtimeFeatureDefinition = {
      id: 'sdk_custom_validator-runtime',
      discovery: {
      viewElements: [],
      validators: [
      {
      type: 'usr.VerifyRequestNameValidator',
      },
      ],
      },
      loadDesignerDefinitions: (context: RemoteDesignerDefinitionsLoadContext) =>
      import('./runtime.designer-definitions').then(
      (m) => m.loadRuntimeDesignerDefinitions(context)),
      activate: () =>
      import('./runtime.feature-activation').then((m) => m.activateRuntimeFeature()),
      } satisfies RemoteFeatureDefinition;
    6. Import the required functionality from the libraries into the files.

    7. Save the files.

  6. Run the npm run build command in the Visual Studio Code terminal to build the project.

As a result, the build will be added to the "dist" directory of the Angular project. The build will have the "sdk_custom_validator" name.

4. Add the validator to the Freedom UI page​

  1. Repeat steps 1-5 of the instructions: Add the custom Freedom UI component to the Freedom UI page. For this example, create a Requests app.

  2. Click btn_actions_in_freedom_ui_designer.png → Source code to open the source code of the Freedom UI page.

  3. Bind the usr.VerifyRequestNameValidator validator to the UsrName model attribute in the viewModelConfigDiff schema section.

    viewModelConfigDiff schema section
    viewModelConfigDiff: /**SCHEMA_VIEW_MODEL_CONFIG_DIFF*/[
    {
    "operation": "merge",
    "path": [
    "attributes"
    ],
    "values": {
    "UsrName": {
    "modelConfigDiff": {
    "path": "PDS.UsrName"
    },
    "validators": {
    "usr.VerifyRequestNameValidator": {
    "type": "usr.VerifyRequestNameValidator",
    "params": {
    "maxLength": 10
    }
    }
    }
    },
    }
    }
    ]/**SCHEMA_VIEW_MODEL_CONFIG_DIFF*/,
  4. Click Save.

As a result, the custom validator will be added to the request page.

View the result​

  1. Open the Requests section.
  2. Create a request that has an arbitrary name. For example, "Vacation."

As a result, Creatio will display an error message because the prefix in the Name field is omitted. The validator is implemented using a remote module created in the Angular framework. View the result >>>


Resources​

*.zip archive that contains the implemented Freedom UI app (for Creatio version 8.3.4 and later)

Angular project that contains the implemented example (for Creatio version 8.3.4 and later)


Example implementation in Creatio 8.3.3 and earlier​

1. Create an Angular project​

To create an Angular project, follow the instructions: Create an Angular project.

For this example:

  • <%projectName%> macro is set to "sdk_custom_validator."
  • <%vendorPrefix%> macro is set to "usr."

As a result, an Angular project to develop a custom validator using a remote module will be added.

2. Install npm packages​

To install npm packages, follow the instructions: Install npm packages.

As a result, required npm packages are installed.

3. Create a custom validator​

  1. Run the ng g class verify-request-name.validator command in the Visual Studio Code terminal to create an Angular class in the project. This adds the VerifyRequestNameValidator class file to the "src/app" project directory.

  2. Implement the validator.

    1. Open the "verify-request-name.validator.ts" file.
    2. Flag the VerifyRequestNameValidator class using the @CrtValidator decorator.
    3. Extend the BaseValidator class from the @creatio-devkit/common library.
    4. Override the async field.
    5. Override the validate() method that validates data in the field.
    6. Import the required functionality from the libraries into the class.
    7. Save the file.
    "verify-request-name.validator.ts" file
    /* Import the required functionality from the libraries. */
    import {
    BaseValidator,
    CrtControlState,
    CrtValidationErrors,
    CrtValidator,
    ValidatorParametersValues
    } from '@creatio-devkit/common';

    export const REQUEST_NAME_PREFIX = new InjectionToken<string>('REQUEST_NAME_PREFIX');

    /* Add the CrtValidator decorator to the VerifyRequestNameValidator class. */
    @CrtValidator({
    type: 'usr.VerifyRequestNameValidator',
    })

    export class VerifyRequestNameValidator extends BaseValidator {

    /* Inject the dependency using the @CrtInject decorator. */
    constructor(@CrtInject(REQUEST_NAME_PREFIX) private _prefix: string) {
    super();
    }

    protected override async = false;

    public validate(
    control: CrtControlState,
    params?: ValidatorParametersValues
    ): CrtValidationErrors | null {
    const value = control.value as string;
    const maxLength = (params as { maxLength?: number } | undefined)?.maxLength;
    if (
    value &&
    (!value.startsWith(this._prefix) ||
    (typeof maxLength === 'number' && value.length > maxLength))
    ) {
    return {
    error: {
    message: 'Add "REQ-" prefix',
    },
    };
    }
    return null;
    }
    }
  3. Inject dependencies.

    1. Open the "verify-request-name.validator.ts" file.
    2. Create the REQUEST_NAME_PREFIX injection token using the InjectionToken class. Use the token to work with Angular DI (dependency injection).
    3. Inject the dependency into the constructor of the VerifyRequestNameValidator class using the @CrtInject decorator.
    4. Import the required functionality from the libraries into the class.
    5. Save the file.
    "verify-request-name.validator.ts" file
    /* Import the required functionality from the libraries. */
    import { InjectionToken } from "@angular/core";
    import { CrtInject } from "@creatio-devkit/common";

    /* The REQUEST_NAME_PREFIX token that works with Angular DI (dependency injection). */
    export const REQUEST_NAME_PREFIX =
    new InjectionToken<string>('REQUEST_NAME_PREFIX');

    export class VerifyRequestNameValidator extends BaseValidator {
    /* Inject the dependency using the @CrtInject decorator. */
    constructor(@CrtInject(REQUEST_NAME_PREFIX) private _prefix: string) {
    super();
    }

    }
  4. Register the VerifyRequestNameValidator validator and the REQUEST_NAME_PREFIX token.

    1. Open the "app.module.ts" file.

    2. Add the VerifyRequestNameValidator validator to the validators section in the @CrtModule decorator.

    3. Add the configuration object to the providers section in the @NgModule decorator.

      • Set the provide property to "REQUEST_NAME_PREFIX."
      • Set the useValue property to "REQ-."
    4. Implement the resolveDependency() method in the bootstrapCrtModule() method of the AppModule root module. The bootstrapCrtModule() method registers the VerifyRequestNameValidator validator flagged using the @CrtModule decorator. The resolveDependency() method receives the dependencies of the VerifyRequestNameValidator validator.

    5. Import the required functionality from the libraries into the class.

    6. Save the file.

    "app.module.ts" file
    /* Import the required functionality from the libraries. */
    import {
    DoBootstrap,
    Injector,
    NgModule,
    ProviderToken
    } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';
    import { bootstrapCrtModule, CrtModule } from '@creatio-devkit/common';
    import {
    VerifyRequestNameValidator,
    REQUEST_NAME_PREFIX
    } from "./verify-request-name.validator";

    @CrtModule({
    /* Specify that VerifyRequestNameValidator is a validator. */
    validators: [VerifyRequestNameValidator],
    })
    @NgModule({
    imports: [BrowserModule],
    providers: [{
    provide: REQUEST_NAME_PREFIX,
    useValue: 'REQ-'
    }],
    })
    export class AppModule implements DoBootstrap {
    constructor(private _injector: Injector) { }

    ngDoBootstrap(): void {
    /* Bootstrap CrtModule definitions. */
    bootstrapCrtModule('sdk_custom_validator', AppModule, {
    resolveDependency: (token) => this._injector.get(<ProviderToken<unknown>>token)
    });
    }
    }
  5. Run the npm run build command in the Visual Studio Code terminal to build the project.

As a result, the build will be added to the "dist" directory of the Angular project. The build will have the "sdk_custom_validator" name.

4. Add the validator to the Freedom UI page​

  1. Repeat steps 1-5 of the instructions: Add the custom Freedom UI component to the Freedom UI page. For this example, create a Requests app.

  2. Click btn_actions_in_freedom_ui_designer.png → Source code to open the source code of the Freedom UI page.

  3. Bind the usr.VerifyRequestNameValidator validator to the UsrName model attribute in the viewModelConfigDiff schema section.

    viewModelConfigDiff schema section
    viewModelConfigDiff: /**SCHEMA_VIEW_MODEL_CONFIG_DIFF*/[
    {
    "operation": "merge",
    "path": [
    "attributes"
    ],
    "values": {
    "UsrName": {
    "modelConfigDiff": {
    "path": "PDS.UsrName"
    },
    "validators": {
    "usr.VerifyRequestNameValidator": {
    "type": "usr.VerifyRequestNameValidator",
    "params": {
    "maxLength": 10
    }
    }
    }
    },
    }
    }
    ]/**SCHEMA_VIEW_MODEL_CONFIG_DIFF*/,
  4. Click Save.

As a result, the custom validator will be added to the request page.

View the result​

  1. Open the Requests section.
  2. Create a request that has an arbitrary name. For example, "Vacation."

As a result, Creatio will display an error message because the prefix in the Name field is omitted. The validator is implemented using a remote module created in the Angular framework. View the result >>>


Resources​

*.zip archive that contains the implemented Freedom UI app (for Creatio version 8.3.3 and earlier)

Angular project that contains the implemented example (for Creatio version 8.3.3 and earlier)