Implement a custom converter using remote module
The example is relevant to Creatio version 8.0.8 and later.
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 instruction in a separate article: 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.converter
command at the command line terminal of Microsoft Visual Studio Code.As a result, Microsoft Visual Studio Code will add the
ConcatConverter
class files to thesrc/app/
project directory. -
Specify that the
ConcatConverter
class is a converter.- Open the
concat.converter.ts
file. - Create the
ConcatConverter
class that implements theConverter<string, string>
interface from the@creatio-devkit/common
library. - Flag the
ConcatConverter
class using theCrtConverter
decorator. - 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.ts
file. - Create the
CONCAT_SEPARATOR_TOKEN
instance of theInjectionToken
class. The token works with Angular DI (dependency injection). - Flag the
CONCAT_SEPARATOR_TOKEN
token using theCrtInject
decorator. - 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
ConcatConverter
converter as a converter and theCONCAT_SEPARATOR_TOKEN
token.-
Open the
app.module.ts
file. -
Add the
ConcatConverter
converter to theconverters
section in theCrtModule
decorator. -
Add the configuration object to the
providers
section in theNgModule
decorator.- Set
provide
property toCONCAT_SEPARATOR_TOKEN
. - Set
useValue
property to space.
- Set
-
Implement the
resolveDependency()
method in thebootstrapCrtModule()
method of theAppModule
root module. ThebootstrapCrtModule()
method registers theConcatConverter
converter flagged using theCrtModule
decorator. TheresolveDependency()
method receives the dependencies of theConcatConverter
converter. -
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 build
command 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.ts
file. - Implement the
convert(value: string, context: ViewModelContext, ...params: string[]): string;
method of theConcatConverter
interface. - 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 build
command 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
caption
property of theLabel
element to the$UsrName
model attribute in theviewConfigDiff
schema section.$UsrName
is the value of the Name field. Add theusr.Converter
converter with the'is the request name'
parameter to the$UsrName
attribute.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*/, -
Click Save on the Client Module Designer’s toolbar.
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
Requests
app page and click Run app. - Click New on the
Requests
app 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*/,
viewModelConfig: /**SCHEMA_VIEW_MODEL_CONFIG*/{
"attributes": {
"UsrName": {
"modelConfig": {
"path": "PDS.UsrName"
}
},
"Id": {
"modelConfig": {
"path": "PDS.Id"
}
}
}
}/**SCHEMA_VIEW_MODEL_CONFIG*/,
modelConfig: /**SCHEMA_MODEL_CONFIG*/{
"dataSources": {
"PDS": {
"type": "crt.EntityDataSource",
"config": {
"entitySchemaName": "UsrRequests"
},
"scope": "page"
},
"AttachmentListDS": {
"type": "crt.EntityDataSource",
"scope": "viewElement",
"config": {
"entitySchemaName": "SysFile",
"attributes": {
"Name": {
"path": "Name"
}
}
}
}
},
"primaryDataSourceName": "PDS"
}/**SCHEMA_MODEL_CONFIG*/,
handlers: /**SCHEMA_HANDLERS*/[]/**SCHEMA_HANDLERS*/,
converters: /**SCHEMA_CONVERTERS*/{}/**SCHEMA_CONVERTERS*/,
validators: /**SCHEMA_VALIDATORS*/{}/**SCHEMA_VALIDATORS*/
};
});