Skip to main content
Version: 10

Custom converter implemented using remote module

Level: advanced

The @creatio-devkit/common library includes a wide set of out-of-the-box converters that cover most data transformation requirements on Freedom UI pages. Learn more: converters schema section. For business scenarios with more specific requirements — for example, transforming a value using an external source or applying custom formatting logic — Creatio lets you implement custom converters and apply them directly to Freedom UI page elements.

Creatio lets you implement custom converters in the following ways:

To implement a custom converter using remote module, complete the following steps.

1. Create an Angular project​

To create an Angular project to develop a custom converter, follow the instructions: Create an Angular project.

2. Install npm packages​

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

3. Create a custom converter​

Creatio lets you implement synchronous or asynchronous custom converters using remote module. The procedure for implementing a custom converter is similar for various types of converters.

To create a custom converter:

  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/converters/some-converter-name.converter command in the Visual Studio Code terminal to create an Angular class in the project, where some-converter-name.converter is a custom class name. This adds the SomeConverterNameConverter class files to the "src/app/features/runtime/converters" project directory.

  3. Specify that the SomeConverterNameConverter class is a converter.

    1. Open the "some-converter-name.converter.ts" file.

    2. Create the SomeConverterNameConverter class that implements the interface from the @creatio-devkit/common library. The SomeConverterNameConverter class implements one of the following interfaces:

      • Converter<V, R> for synchronous converters.
      • Converter<V, Promise<R>> for asynchronous converters.

      Where V is the type of the convertible attribute and R is the type of the conversion result.

    3. Flag the SomeConverterNameConverter class using the @CrtConverter decorator.

    4. Import the required functionality from the libraries into the file.

    5. Save the file.

    "some-converter-name.converter.ts" file
    /* Import the required functionality from the libraries. */
    import { Converter, CrtConverter } from "@creatio-devkit/common";

    /* Register the SomeConverterNameConverter as a Freedom UI converter. */
    @CrtConverter({
    type: 'usr.SomeConverterNameConverter',
    })

    /* The class for synchronous converters. */
    export class SomeConverterNameConverter implements Converter<string, string> {
    }

    /* The class for asynchronous converters. */
    export class SomeConverterNameConverter implements Converter<string, Promise<string>> {
    }
  4. Inject dependencies.

    1. Open the "some-converter-name.converter.ts" file.
    2. Create the SOME_TOKEN_NAME injection token using the InjectionToken class. Use the token to work with Angular DI (dependency injection). Alternatively, you can inject a client web service directly using Angular DI instead of using an injection token.
    3. Inject the dependency into the constructor of the SomeConverterNameConverter class using the @CrtInject decorator.
    4. Import the required functionality from the libraries into the file.
    5. Save the file.
    "some-converter-name.converter.ts" file
    /* Import the required functionality from the libraries. */
    import { InjectionToken } from "@angular/core";
    import { Converter, CrtInject } from "@creatio-devkit/common";

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

    /* The class for synchronous converters. */
    export class SomeConverterNameConverter implements Converter<string, string> {
    constructor(@CrtInject(SOME_TOKEN_NAME) private _separator: string) { };
    }

    /* The class for asynchronous converters. */
    export class SomeConverterNameConverter implements Converter<string, Promise<string>> {
    constructor(@CrtInject(SOME_TOKEN_NAME) private _separator: string) { };
    }
  5. Register the SomeConverterNameConverter converter and the SOME_TOKEN_NAME token. The template already contains the runtime feature activation and bootstrapCrtModule() call. Extend the existing runtime feature files to register the converter.

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

    2. Add the SomeConverterNameConverter converter to the converters section in the @CrtModule decorator.

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

      • Set the provide property to "SOME_TOKEN_NAME."
      • Set the useValue property to ' ' (a single space).
      "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 {
      SomeConverterNameConverter,
      SOME_TOKEN_NAME
      } from './converters/some-converter-name.converter';

      @CrtModule({
      /* Specify that SomeConverterNameConverter is a converter. */
      converters: [SomeConverterNameConverter]
      })
      @NgModule({
      declarations: [],
      imports: [BrowserModule],
      providers: [
      {
      provide: SOME_TOKEN_NAME,
      useValue: ' '
      },
      ],
      })
      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 converter to the discovery.converters section.

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

      export const runtimeFeatureDefinition = {
      id: 'some-converter-name-runtime',
      discovery: {
      viewElements: [],
      converters: [
      {
      type: 'usr.SomeConverterNameConverter'
      }
      ],
      },
      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. Implement the conversion of an incoming value.

    1. Open the "some-converter-name.converter.ts" file.

    2. Implement a method of the SomeConverterNameConverter interface. Implement one of the following methods:

      • convert(value: V, context: ViewModelContext, ...params: unknown[]): R; for synchronous converters.
      • async convert(value: V, context: ViewModelContext, ...params: unknown[]): R; for asynchronous converters.

      Where V is the type of the convertible attribute and R is the type of the conversion result.

    3. Import the required functionality from the libraries into the file.

    4. Save the file.

    "some-converter-name.converter.ts" file
    /* Import the required functionality from the libraries. */
    import { Converter, ViewModelContext } from "@creatio-devkit/common";

    /* The class for synchronous converters. */
    export class SomeConverterNameConverter implements Converter<string, string> {

    /* Implement the convert() method for synchronous converters. */
    public convert(
    value: string,
    context: ViewModelContext,
    ...params: string[]
    ): string {
    return [value, ...params].join(this._separator);
    }
    }

    /* The class for asynchronous converters. */
    export class SomeConverterNameConverter implements Converter<string, Promise<string>> {

    /* Implement the convert() method for asynchronous converters. */
    public async convert(
    value: string,
    context: ViewModelContext,
    ...params: string[]
    ): Promise<string> {
    /* Implement some async action. */

    await new Promise(function(resolve) {
    setTimeout(resolve, 100);
    });
    return [value, ...params].join(this._separator);
    }
    }
  7. 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.

4. Add the converter to the Freedom UI page​

  1. Repeat steps 1-5 of the instructions: Add the custom Freedom UI component to the Freedom UI page.

  2. Bind the usr.SomeConverterNameConverter converter to the needed property of the corresponding model attribute in the viewConfigDiff schema section. Creatio lets you set converter parameters. Learn more: Implement field value conversion.

    viewConfigDiff schema section
    viewConfigDiff: /**SCHEMA_VIEW_CONFIG_DIFF*/[
    {
    "operation": "insert",
    "name": "SomeComponentName",
    "values": {
    /* Apply converter to the $SomeAttributeName attribute.
    Use a synchronous or asynchronous converter. */
    "caption": "$SomeAttributeName | usr.SomeConverterNameConverter :'SomeConverterParameter'",
    },
    }
    ]/**SCHEMA_VIEW_CONFIG_DIFF*/,
  3. Click Save.

As a result, the custom converter will be applied to the corresponding element on the Freedom UI page.


See also​

Custom Freedom UI component implemented using remote module

Implement the conversion of a field value on a page

Customize page fields

converters schema section


Resources​

Remote module template