Implement a custom converter using remote module
Add a converter that adds the is the request name string to the Name field value of the custom Requests section. Display the converted value in the Label type component. Implement the synchronous converter using a remote module created in Angular framework.
1. Create an Angular project to develop a custom converter using remote module
To create an Angular project to develop a custom converter using remote module, follow the instructions: Implement custom UI component using remote module.
2. Create a custom converter using remote module
-
Create an Angular class in the project. To do this, run the
ng g class concat.convertercommand at the command line terminal of Microsoft Visual Studio Code.As a result, Microsoft Visual Studio Code will add the
ConcatConverterclass files to thesrc/app/project directory.
-
Specify that the
ConcatConverterclass is a converter.- Open the
concat.converter.tsfile. - Create the
ConcatConverterclass that implements theConverter<string, string>interface from the@creatio-devkit/commonlibrary. - Flag the
ConcatConverterclass using theCrtConverterdecorator. - Import the required functionality from the libraries into the class.
- Save the file.
concat.converter.ts file/* Import the required functionality from the libraries. */
import { Converter, CrtConverter } from "@creatio-devkit/common";
/* Add the CrtConverter decorator to the ConcatConverter interface. */
@CrtConverter({
type: 'usr.ConcatConverter',
})
export class ConcatConverter implements Converter<string, string> {
} - Open the
-
Inject dependencies.
- Open the
concat.converter.tsfile. - Create the
CONCAT_SEPARATOR_TOKENinstance of theInjectionTokenclass. The token works with Angular DI (dependency injection). - Flag the
CONCAT_SEPARATOR_TOKENtoken using theCrtInjectdecorator. - Import the required functionality from the libraries into the class.
- Save the file.
concat.converter.ts file/* Import the required functionality from the libraries. */
import { InjectionToken } from "@angular/core";
import { Converter, CrtInject } from "@creatio-devkit/common";
/* The CONCAT_SEPARATOR_TOKEN token that works with Angular DI (dependency injection). */
export const CONCAT_SEPARATOR_TOKEN = new InjectionToken<string>('CONCAT_SEPARATOR_TOKEN');
...
export class ConcatConverter implements Converter<string, string> {
constructor(@CrtInject(CONCAT_SEPARATOR_TOKEN) private _separator: string) { };
} - Open the
-
Register the
ConcatConverterconverter as a converter and theCONCAT_SEPARATOR_TOKENtoken.-
Open the
app.module.tsfile. -
Add the
ConcatConverterconverter to theconverterssection in theCrtModuledecorator. -
Add the configuration object to the
providerssection in theNgModuledecorator.- Set
provideproperty toCONCAT_SEPARATOR_TOKEN. - Set
useValueproperty to space.
- Set
-
Implement the
resolveDependency()method in thebootstrapCrtModule()method of theAppModuleroot module. ThebootstrapCrtModule()method registers theConcatConverterconverter flagged using theCrtModuledecorator. TheresolveDependency()method receives the dependencies of theConcatConverterconverter. -
Import the required functionality from the libraries into the class.
-
Save the file.
app.module.ts file/* Import the required functionality from the libraries. */
import { DoBootstrap, Injector, NgModule, ProviderToken } from '@angular/core';
import { bootstrapCrtModule, CrtModule } from '@creatio-devkit/common';
import { ConcatConverter, CONCAT_SEPARATOR_TOKEN } from './concat.converter';
@CrtModule({
...,
/* Specify that ConcatConverter is a converter. */
converters: [ConcatConverter]
})
@NgModule({
...,
providers: [
{
provide: CONCAT_SEPARATOR_TOKEN,
useValue: ' '
},
],
})
export class AppModule implements DoBootstrap {
constructor(private _injector: Injector) {}
ngDoBootstrap(): void {
/* Bootstrap CrtModule definitions. */
bootstrapCrtModule('sdk_remote_module_package', AppModule, {
resolveDependency: (token) => this._injector.get(<ProviderToken<unknown>>token),
});
}
} -
-
Build the project. To do this, run the
npm run buildcommand at the command line terminal of Microsoft Visual Studio Code.
As a result, Microsoft Visual Studio Code will add the build to the dist directory of the Angular project. The build will have the sdk_remote_module_package name.
3. Implement the business logic of the custom converter using remote module
-
Implement the conversion of an incoming value.
- Open the
concat.converter.tsfile. - Implement the
convert(value: string, context: ViewModelContext, ...params: string[]): string;method of theConcatConverterinterface. - Import the required functionality from the libraries into the class.
- Save the file.
concat.converter.ts file/* Import the required functionality from the libraries. */
import { Converter, ViewModelContext } from "@creatio-devkit/common";
...
export class ConcatConverter implements Converter<string, string> {
...
/* Implement the convert() method. */
public convert(value: string, context: ViewModelContext, ...params: string[]): string {
return [value, ...params].join(this._separator);
}
} - Open the
-
Build the project. To do this, run the
npm run buildcommand at the command line terminal of Microsoft Visual Studio Code.
As a result, Microsoft Visual Studio Code will add the build to the dist directory of the Angular project. The build will have the sdk_remote_module_package name.
4. Add the converter implemented using remote module to the Freedom UI page
-
Repeat steps 1-7 of the procedure to Implement custom UI component using remote module.
-
Add a Label type component to the working area of the Freedom UI Designer.
-
Click the
button in the action panel of the Freedom UI Designer. After you save the page settings, Creatio opens the source code of the Freedom UI page. -
Bind the
captionproperty of theLabelelement to the$UsrNamemodel attribute in theviewConfigDiffschema section.$UsrNameis the value of the Name field. Add theusr.Converterconverter with the'is the request name'parameter to the$UsrNameattribute.viewConfigDiff schema sectionviewConfigDiff: /**SCHEMA_VIEW_CONFIG_DIFF*/[
...,
{
"operation": "insert",
"name": "Label",
"values": {
...,
/* Apply the usr.ConcatConverter converter to the $UsrName attribute. */
"caption": "$UsrName | usr.ConcatConverter : 'is the request name'",
...
},
...
}
]/**SCHEMA_VIEW_CONFIG_DIFF*/, -
Save the changes.
As a result, Creatio will add the converter to the Freedom UI page.
Outcome of the example
To view the outcome of the example:
- Open the
Requestsapp page and click Run app. - Click New on the
Requestsapp toolbar. - Enter "REQ-001" in the Name input.
As a result, Creatio will display the converted value on the request page. The synchronous converter is implemented using a remote module created in Angular framework.

Source code
- app.module.ts file
- concat.converter.ts file
- UsrRequests_FormPage
/* 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 { ConcatConverter, CONCAT_SEPARATOR_TOKEN } from './concat.converter';
@CrtModule({
/* Specify that component is a view element. */
viewElements: [],
/* Specify that ConcatConverter is a converter. */
converters: [ConcatConverter]
})
@NgModule({
declarations: [],
imports: [BrowserModule],
providers: [
{
provide: CONCAT_SEPARATOR_TOKEN,
useValue: ' '
},
],
})
export class AppModule implements DoBootstrap {
constructor(private _injector: Injector) {}
ngDoBootstrap(): void {
/* Bootstrap CrtModule definitions. */
bootstrapCrtModule('sdk_remote_module_package', AppModule, {
resolveDependency: (token) => this._injector.get(<ProviderToken<unknown>>token),
});
}
}
/* Import the required functionality from the libraries. */
import { InjectionToken } from "@angular/core";
import { Converter, CrtConverter, CrtInject, ViewModelContext } from "@creatio-devkit/common";
/* The CONCAT_SEPARATOR_TOKEN token that works with Angular DI (dependency injection). */
export const CONCAT_SEPARATOR_TOKEN = new InjectionToken<string>('CONCAT_SEPARATOR_TOKEN');
/* Add the CrtConverter decorator to the ConcatConverter interface. */
@CrtConverter({
type: 'usr.ConcatConverter',
})
export class ConcatConverter implements Converter<string, string> {
constructor(@CrtInject(CONCAT_SEPARATOR_TOKEN) private _separator: string) { };
/* Implement the convert() method. */
public convert(value: string, context: ViewModelContext, ...params: string[]): string {
return [value, ...params].join(this._separator);
}
}
define("UsrRequests_FormPage", /**SCHEMA_DEPS*/[]/**SCHEMA_DEPS*/, function/**SCHEMA_ARGS*/()/**SCHEMA_ARGS*/ {
return {
viewConfigDiff: /**SCHEMA_VIEW_CONFIG_DIFF*/[
{
"operation": "merge",
"name": "Feed",
"values": {
"dataSourceName": "PDS",
"entitySchemaName": "UsrRequests"
}
},
{
"operation": "merge",
"name": "AttachmentList",
"values": {
"columns": [
{
"id": "df093806-a8ed-40ae-979c-770bec690b3c",
"code": "AttachmentListDS_Name",
"caption": "#ResourceString(AttachmentListDS_Name)#",
"dataValueType": 28,
"width": 200
}
]
}
},
{
"operation": "insert",
"name": "UsrName",
"values": {
"layoutConfig": {
"column": 1,
"row": 1,
"colSpan": 1,
"rowSpan": 1
},
"type": "crt.Input",
"label": "$Resources.Strings.UsrName",
"control": "$UsrName",
"labelPosition": "auto"
},
"parentName": "SideAreaProfileContainer",
"propertyName": "items",
"index": 0
},
{
"operation": "insert",
"name": "Label",
"values": {
"layoutConfig": {
"column": 1,
"row": 2,
"colSpan": 1,
"rowSpan": 1
},
"type": "crt.Label",
/* Apply the usr.ConcatConverter converter to the $UsrName attribute. */
"caption": "$UsrName | usr.ConcatConverter : 'is the request name'",
"labelType": "body",
"labelThickness": "default",
"labelEllipsis": false,
"labelColor": "auto",
"labelBackgroundColor": "transparent",
"labelTextAlign": "start",
"visible": true
},
"parentName": "SideAreaProfileContainer",
"propertyName": "items",
"index": 1
}
]/**SCHEMA_VIEW_CONFIG_DIFF*/,
viewModelConfigDiff: /**SCHEMA_VIEW_MODEL_CONFIG_DIFF*/[
{
"operation": "merge",
"path": [
"attributes"
],
"values": {
"UsrName": {
"modelConfigDiff": {
"path": "PDS.UsrName"
}
},
"Id": {
"modelConfigDiff": {
"path": "PDS.Id"
}
}
}
}
]/**SCHEMA_VIEW_MODEL_CONFIG_DIFF*/,
modelConfigDiff: /**SCHEMA_MODEL_CONFIG_DIFF*/[
{
"operation": "merge",
"path": [
"dataSources"
],
"values": {
"PDS": {
"type": "crt.EntityDataSource",
"config": {
"entitySchemaName": "UsrRequests"
},
"scope": "page"
},
"AttachmentListDS": {
"type": "crt.EntityDataSource",
"scope": "viewElement",
"config": {
"entitySchemaName": "SysFile",
"attributes": {
"Name": {
"path": "Name"
}
}
}
}
},
{
"operation": "merge",
"path": [],
"values": {
"primaryDataSourceName": "PDS"
}
}
}
]/**SCHEMA_MODEL_CONFIG_DIFF*/,
handlers: /**SCHEMA_HANDLERS*/[]/**SCHEMA_HANDLERS*/,
converters: /**SCHEMA_CONVERTERS*/{}/**SCHEMA_CONVERTERS*/,
validators: /**SCHEMA_VALIDATORS*/{}/**SCHEMA_VALIDATORS*/
};
});