Skip to main content
Version: 8.1

Customize sidebars

Level: intermediate

Sidebars are special pages you can view by clicking the buttons in the top right of the Creatio UI, for example, feed or chats. Learn more: Set up a sidebar (user documentation).

Migrate a Classic UI panel to Freedom UI

note

This functionality is available in beta version in Creatio 8.1.3. To access the functionality, turn on the "SidebarExtensions" and "ShowPageAddonsPropertiesPanel" additional features in Creatio 8.1.4 or "SidePanelExtensions" additional feature in Creatio 8.1.3. Instructions: Change the status of an additional feature for all users.

Detailed example: Migrate a Classic UI panel to Freedom UI.

1. Create a sidebar

  1. Create a new Freedom UI app or open an existing app. Instructions: Create an app manually (user documentation).

  2. Create a Freedom UI page to use as a sidebar. To do this, click New pageBlank pageSelect. Make sure to use only Blank page template to ensure backwards compatibility of sidebars.

  3. Open the sidebar properties. To do this, click AdvancedSidebar. This opens a window.

  4. Fill out the sidebar properties.

    Property

    Property description

    Title

    Localizable sidebar name displayed above its content.

    Code

    The sidebar schema name. Starts with the prefix. Learn more: Manage configuration elements. Can contain Latin characters and digits.

    Location

    Location of the sidebar in an existing Freedom UI panel.

    Sidebar icon

    Icon of the sidebar.

    Sidebar position

    Sidebar order number in the Freedom UI panel. Out of the box, the position numbering is 1000, 2000, 3000, etc. Enter the number between these numbers to place the sidebar between existing sidebars.

  5. Save the changes.

As a result, the sidebar will be created without being displayed on Freedom UI panel.

2. Implement loading a Classic UI custom panel in Freedom UI

  1. Open the source code of the Freedom UI page to migrate a Classic UI panel. To do this, click .

  2. Set up the binding parameters of client module schema that implements functionality of the Classic UI custom panel.

    1. Go to the viewConfigDiff schema section.

    2. Add the configuration object that configures Classic UI custom panel.

    3. Fill out the properties of binding parameters directly or using BaseSchemaModuleV2.

      Directly

      Fill out the properties of binding parameters directly for panels that do not inherit functionality of base client module schemas. To do this, use the following properties.

      Property

      Property value

      type

      crt.ModuleLoader

      module

      Code of the client module schema that implements functionality of the Classic UI custom panel

      View an example that binds the SomeClassicUIPanel client module schema to the SomeApp_FormPage Freedom UI page schema directly below.

      SomeApp_FormPage
      /* Declare the AMD module. */
      define("SomeApp_FormPage", /**SCHEMA_DEPS*/[] /**SCHEMA_DEPS*/, function/**SCHEMA_ARGS*/()/**SCHEMA_ARGS*/ {
      return {
      viewConfigDiff: /**SCHEMA_VIEW_CONFIG_DIFF*/[
      /* Configuration object that binds the "SomeClassicUIPanel" client module schema. */
      {
      "operation": "insert",
      "name": "SomeClassicUIPanel",
      "values": {
      "type": "crt.ModuleLoader",
      /* "SomeClassicUIPanel" client module schema that implements functionality of the Classic UI custom panel. */
      "module": "SomeClassicUIPanel"
      },
      "parentName": "MainContainer",
      "propertyName": "items",
      "index": 0
      }
      ]/**SCHEMA_VIEW_CONFIG_DIFF*/,
      viewModelConfigDiff: /**SCHEMA_VIEW_MODEL_CONFIG_DIFF*/[]/**SCHEMA_VIEW_MODEL_CONFIG_DIFF*/,
      modelConfigDiff: /**SCHEMA_MODEL_CONFIG_DIFF*/[]/**SCHEMA_MODEL_CONFIG_DIFF*/,
      handlers: /**SCHEMA_HANDLERS*/[]/**SCHEMA_HANDLERS*/,
      converters: /**SCHEMA_CONVERTERS*/{}/**SCHEMA_CONVERTERS*/,
      validators: /**SCHEMA_VALIDATORS*/{}/**SCHEMA_VALIDATORS*/
      };
      });

      Using BaseSchemaModuleV2

      Fill out the properties of binding parameters for panels that inherit functionality of base client module schemas. To do this, use the following properties.

      Property

      Property value

      type

      crt.ModuleLoader

      module

      BaseSchemaModuleV2

      useHistoryState

      false

      isSchemaConfigInitialized

      true

      schemaName

      Code of the client module schema that implements functionality of the Classic UI custom panel

      View an example that binds the SomeClassicUIPanel client module schema to the SomeApp_FormPage Freedom UI page schema using BaseSchemaModuleV2 below.

      SomeApp_FormPage
      /* Declare the AMD module. */
      define("SomeApp_FormPage", /**SCHEMA_DEPS*/[] /**SCHEMA_DEPS*/, function/**SCHEMA_ARGS*/()/**SCHEMA_ARGS*/ {
      return {
      viewConfigDiff: /**SCHEMA_VIEW_CONFIG_DIFF*/[
      /* Configuration object that binds the "SomeClassicUIPanel" client module schema. */
      {
      "operation": "insert",
      "name": "SomeClassicUIPanel",
      "values": {
      "type": "crt.ModuleLoader",
      "module": "BaseSchemaModuleV2",
      "instanceConfig": {
      "useHistoryState": false,
      "isSchemaConfigInitialized": true,
      /* "SomeClassicUIPanel" client module schema that implements functionality of the Classic UI custom panel. */
      "schemaName": "SomeClassicUIPanel"
      }
      },
      "parentName": "MainContainer",
      "propertyName": "items",
      "index": 0
      }
      ]/**SCHEMA_VIEW_CONFIG_DIFF*/,
      viewModelConfigDiff: /**SCHEMA_VIEW_MODEL_CONFIG_DIFF*/[]/**SCHEMA_VIEW_MODEL_CONFIG_DIFF*/,
      modelConfigDiff: /**SCHEMA_MODEL_CONFIG_DIFF*/[]/**SCHEMA_MODEL_CONFIG_DIFF*/,
      handlers: /**SCHEMA_HANDLERS*/[]/**SCHEMA_HANDLERS*/,
      converters: /**SCHEMA_CONVERTERS*/{}/**SCHEMA_CONVERTERS*/,
      validators: /**SCHEMA_VALIDATORS*/{}/**SCHEMA_VALIDATORS*/
      };
      });
  3. Save the changes.

As a result, Creatio will load a Classic UI custom panel in Freedom UI as a sidebar.

Manage sidebar events implemented using remote module

note

This functionality is available in beta version in Creatio 8.1.4. To access the functionality, turn on the "SidebarExtensions" and "ShowPageAddonsPropertiesPanel" additional features. Instructions: Change the status of an additional feature for all users.

1. Set up the page UI

  1. Enable the sidebar functionality in Creatio. To do this, change the status of the "SidebarExtensions" and "ShowPageAddonsPropertiesPanel" additional features. Instructions: Change the status of an additional feature for all users.
  2. Create a sidebar. Read more >>>
  3. Set up the sidebar page based on your business goals.

2. Create an Angular project

Instructions: Create an Angular project to develop a custom UI component using remote module.

3. Create a custom sidebar using remote module

  1. Create an Angular component that implements a custom sidebar. Instructions: Create a custom UI component using remote module.

  2. Add a constant that stores data of the custom sidebar code. Take this step if you need to implement multiple sidebar events.

    1. Go to the src/app/ directory.

    2. Create the constants directory.

    3. Go to the src/app/constants directory.

    4. Create the sidebar-constants.ts and index.ts files.

    5. Open the sidebar-constants.ts file.

    6. Export a constant that includes the value of the custom sidebar code.

      View an example that exports the SOME_SIDEBAR_CODE constant below. The SOME_SIDEBAR_CODE constant includes an arbitrary UsrSomeCustomSidebar code of the custom sidebar.

      sidebar-constants.ts file
      /* Export a constant that includes the value of the custom sidebar code. */
      export const SOME_SIDEBAR_CODE = 'UsrSomeCustomSidebar';
    7. Save the file.

    8. Open the index.ts file.

    9. Export the required functionality from the module.

    10. Save the file.

      index.ts file
      /* Export the required functionality from the module. */
      export * from './sidebar-constants';

4. Create a custom service

  1. Go to the src/app/ directory.
  2. Create the services directory.
  3. Go to the src/app/services directory.
  4. Implement the business logic. Instructions: Create a custom service using remote module.

5. Create requests and events of the custom sidebar

  1. Enable the HttpClientService service that sends HTTP requests.

    1. Open the app.module.ts file.
    2. Add the HttpClientService service to the providers section in the NgModule decorator.
    3. Import the required functionality from the libraries into the class.
    4. Save the file.
    app.module.ts file
    /* Import the required functionality from the libraries. */
    import { NgModule } from '@angular/core';
    import { HttpClientService } from '@creatio-devkit/common';

    ...

    @NgModule({
    ...,
    providers: [HttpClientService],
    })

    ...
  2. Create an Angular class in the project. To do this, run the ng g class open-close-some-sidebar.handler command at the command line terminal of Microsoft Visual Studio Code.

    As a result, Microsoft Visual Studio Code will add the OpenCloseSomeSidebarHandler class files to the src/app/ project directory. The OpenCloseSomeSidebarHandler class implements open and close events of the custom sidebar.

  3. Implement open and close events of the custom sidebar (optional).

    1. Open the open-close-some-sidebar.handler.ts file.

    2. Add the SomeSidebarEventRequest class and inherit the BaseRequestHandler class from the @creatio-devkit/common library.

    3. Add the configuration object that declares the request handler.

      Property

      Property value

      Property description

      type

      usr.OpenCloseSomeSidebarHandler

      Custom request handler.

      requestType

      crt.HandleSidebarOpenRequest

      Base request handler that opens the custom sidebar.

      crt.HandleSidebarCloseRequest

      Base request handler that closes the custom sidebar.

    4. Flag the OpenCloseSomeSidebarHandler class using the CrtRequestHandler decorator.

    5. Implement the business logic of the handle(request: SomeSidebarEventRequest) method. The method handles the user request. Since the request handler interacts with crt.HandleSidebarOpenRequest and crt.HandleSidebarCloseRequest request handlers from all sidebars, check the sidebar code. If the sidebar is available, implement the custom business logic.

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

    7. Save the file.

    View an example that implements open and close events of the custom sidebar below.

    open-sidebar.handler.ts file
    /* Import the required functionality from the libraries. */
    import { BaseRequest, BaseRequestHandler, CrtRequestHandler } from "@creatio-devkit/common";
    import { SOME_SIDEBAR_CODE } from "./constants";

    class SomeSidebarEventRequest extends BaseRequest {
    public readonly sidebarCode!: string;
    }

    @CrtRequestHandler({
    type: 'usr.OpenCloseSomeSidebarHandler',
    /* Open event of the custom sidebar. */
    requestType: "crt.HandleSidebarOpenRequest",
    /* Close event of the custom sidebar. */
    //requestType: "crt.HandleSidebarCloseRequest",
    })
    export class OpenCloseSomeSidebarHandler extends BaseRequestHandler {

    public async handle(request: SomeSidebarEventRequest): Promise<void> {
    /* Check the sidebar code. */
    if (request.sidebarCode === SOME_SIDEBAR_CODE) {
    /* Implement the custom business logic. */
    ...;
    }
    /* Call the next handler if it exists and return its result. */
    await this.next?.handle(request);
    }
    }
  4. Create an Angular class in the project. To do this, run the ng g class initialize-some-sidebar.handler command at the command line terminal of Microsoft Visual Studio Code.

    As a result, Microsoft Visual Studio Code will add the InitializeSomeSidebarHandler class files to the src/app/ project directory. The InitializeSomeSidebarHandler class initializes the custom sidebar.

  5. Implement events that initialize the custom sidebar.

    1. Open the initialize-some-sidebar.handler.ts file.

    2. Add the configuration object that declares the request handler.

      Property

      Property value

      Property description

      type

      usr.SomeSidebarInitHandler

      Custom request handler.

      requestType

      crt.SidebarInitRequest

      Base request handler that initializes the custom sidebar.

    3. Flag the InitializeSomeSidebarHandler class using the CrtRequestHandler decorator.

    4. Inherit the BaseRequestHandler class from the @creatio-devkit/common library.

    5. Create an instance of the HTTP client from the @creatio-devkit/common library.

    6. Create an instance of the custom service.

    7. Implement the business logic of events based on your business goals.

      Event that returns the state of the custom sidebar

      Check whether the sidebar is available before executing custom actions to initialize the sidebar. This prevents functionality issues if the user disables the sidebar or if the sidebar is restricted by access rights. The crt.GetSidebarStateRequest request handler returns the state of the custom sidebar.

      View an example of the event that returns the state of the custom sidebar below.

      initialize-some-sidebar.handler.ts file
      /* Import the required functionality from the libraries. */
      import { BaseRequest, BaseRequestHandler, CrtRequestHandler } from "@creatio-devkit/common";
      import { SOME_SIDEBAR_CODE } from "./constants";

      /* Interface that explicitly specifies the type of the returned "GetUnreadMessages" request. */
      interface GetUnreadMessagesResponse {
      messages: string[];
      }

      @CrtRequestHandler({
      type: 'usr.SomeSidebarInitHandler',
      requestType: 'crt.SidebarInitRequest',
      })

      export class InitializeSomeSidebarHandler extends BaseRequestHandler {

      /* Return the sidebar state. */
      private async _getSidebarState(): Promise<{ available: boolean, opened: boolean }> {
      return (await this.handlerChain.process({
      type: 'crt.GetSidebarStateRequest',
      sidebarCode: SOME_SIDEBAR_CODE,
      $context: {}
      } as BaseRequest)) as { available: boolean, opened: boolean };
      }

      }
      • If the custom sidebar whose code is specified in the sidebarCode property is available to the user, the available property is set to true. Otherwise, false.
      • If the custom sidebar is open, the opened property is set to true. Otherwise, false.
      • Since Creatio handles the initialization request before the sidebar is opened, if you send a request that returns the state of the custom sidebar using the crt.SidebarInitRequest request handler, the opened property is always set to false.
      Event that displays or hides the notification mark on the sidebar icon

      To display the notification mark, use the crt.ShowSidebarNotificationMarkRequest request handler.

      To hide the notification mark, use the crt.HideSidebarNotificationMarkRequest request handler.

      View an example of the event that displays or hides the notification mark on the sidebar icon below.

      initialize-some-sidebar.handler.ts file
      /* Import the required functionality from the libraries. */
      import { BaseRequest, BaseRequestHandler, CrtRequestHandler } from "@creatio-devkit/common";
      import { SOME_SIDEBAR_CODE } from "./constants";

      interface GetUnreadMessagesResponse {
      messages: string[];
      }

      @CrtRequestHandler({
      type: 'usr.SomeSidebarInitHandler',
      requestType: 'crt.SidebarInitRequest',
      })

      export class InitializeSomeSidebarHandler extends BaseRequestHandler {

      /* Display a notification mark on the sidebar icon. */
      private async _showNotificationMark(): Promise<void> {
      await this.handlerChain.process({
      type: 'crt.ShowSidebarNotificationMarkRequest',
      sidebarCode: SOME_SIDEBAR_CODE,
      $context: {}
      } as BaseRequest);
      }

      /* Hide a notification mark on the sidebar icon. */
      private async _hideNotificationMark(): Promise<void> {
      await this.handlerChain.process({
      type: 'crt.HideSidebarNotificationMarkRequest',
      sidebarCode: SOME_SIDEBAR_CODE,
      $context: {}
      } as BaseRequest);
      }

      }
      Event that opens or closes the custom sidebar

      To open the custom sidebar, use the crt.OpenSidebarRequest request handler.

      To close the custom sidebar, use the crt.CloseSidebarRequest request handler.

      View an example of the event that opens and closes the custom sidebar below.

      initialize-some-sidebar.handler.ts file
      /* Import the required functionality from the libraries. */
      import { BaseRequest, BaseRequestHandler, CrtRequestHandler } from "@creatio-devkit/common";
      import { SOME_SIDEBAR_CODE } from "./constants";

      interface GetUnreadMessagesResponse {
      messages: string[];
      }

      @CrtRequestHandler({
      type: 'usr.SomeSidebarInitHandler',
      requestType: 'crt.SidebarInitRequest',
      })

      export class InitializeSomeSidebarHandler extends BaseRequestHandler {

      /* Open the sidebar. */
      private async _openSidebar(): Promise<void> {
      await this.handlerChain.process({
      type: 'crt.OpenSidebarRequest',
      sidebarCode: SOME_SIDEBAR_CODE,
      $context: {}
      } as BaseRequest);
      }

      /* Close the sidebar. */
      private async _closeSidebar(): Promise<void> {
      await this.handlerChain.process({
      type: 'crt.CloseSidebarRequest',
      sidebarCode: SOME_SIDEBAR_CODE,
      $context: {}
      } as BaseRequest);
      }

      }
      Additional events that manage the custom sidebar

      Implement the business logic of the additional events if needed.

      Event

      Description of event

      _refreshSidebarData()

      Refreshes sidebar data when the sidebar is opened.

      _checkUnreadMessages()

      Waits for data sent by the web service. When Creatio receives data, displays a notification mark on the sidebar icon.

      _isSidebarAvailable()

      Checks whether the sidebar is available.

      _isSidebarOpened()

      Checks whether the sidebar is open.

      _handleWebServiceEvent()

      Handles the data sent by the web service. If the sidebar is open, refreshes its data. Otherwise, opens the sidebar when the web service sends required data.

      _subscribeToWebServiceEvents()

      Subscribes to the data sent by the web service. When Creatio receives data, handles it.

      handle()

      Handles the user request. If the sidebar is available, waits for data sent by the web service and subscribes to data.

      We recommend avoiding long-term asynchronous operations, such as an HTTP request that loads data, in the init event. Otherwise, it delays the data loading and Creatio proceeds after the request handlers are completed. If executing a long-term operation is necessary, handle data and wait for asynchronous data loading using the then method instead of the await keyword.

      View an example that implements the handling of long-term asynchronous operations below.

      private _loadDataByHttpRequest(): Promise<CustomData> {
      /* Implement the custom business logic. */
      ...;
      }

      public async handle(request: BaseRequest): Promise<void> {
      this._loadDataByHttpRequest().then(data => {
      /* Implement the business logic that handles loaded data. */
      ...;
      });
      await this.next?.handle(request);
      }

      View an example of additional events that manage the custom sidebar below.

      initialize-some-sidebar.handler.ts file
      /* Import the required functionality from the libraries. */
      import { BaseRequest, BaseRequestHandler, CrtRequestHandler, HttpClientService } from "@creatio-devkit/common";
      import { SOME_SIDEBAR_CODE } from "./constants";
      import { SomeService } from "./services/some-service.service";

      interface GetUnreadMessagesResponse {
      messages: string[];
      }

      @CrtRequestHandler({
      type: 'usr.SomeSidebarInitHandler',
      requestType: 'crt.SidebarInitRequest',
      })

      export class InitializeSomeSidebarHandler extends BaseRequestHandler {
      constructor(
      /* Create an instance of the HTTP client from the "@creatio-devkit/common" library. */
      private readonly _httpClient: HttpClientService,
      /* Create an instance of the "SomeService." */
      private readonly _someService: SomeService
      )
      {
      super();
      }

      /* Display a notification mark on the sidebar icon when the web service sends required data. */
      private async _showNotificationMark(): Promise<void> {
      await this.handlerChain.process({
      type: 'crt.ShowSidebarNotificationMarkRequest',
      sidebarCode: SOME_SIDEBAR_CODE,
      $context: {}
      } as BaseRequest);
      }

      /* Open the sidebar when the web service sends required data.*/
      private async _openSidebar(): Promise<void> {
      await this.handlerChain.process({
      type: 'crt.OpenSidebarRequest',
      sidebarCode: SOME_SIDEBAR_CODE,
      $context: {}
      } as BaseRequest);
      }

      /* Wait for data sent by the web service. When Creatio receives data, display a notification mark on the sidebar icon. */
      private async _checkUnreadMessages(): Promise<void> {
      /* Specify the URL to retrieve the list of unread messages. Use the "EventService" web service. */
      const endpointUrl = `rest/EventService/GetUnreadMessages`;
      /* Add some description here. */
      const result = await this._httpClient.post<GetUnreadMessagesResponse>(endpointUrl, null, {
      responseType: 'json',
      });
      /* Check whether a unread message occurs. If it happens, display a notification mark on the sidebar icon. */
      if (result.body && result.body.messages.length > 0) {
      await this._showNotificationMark();
      }
      }

      /* Return the sidebar state. */
      private async _getSidebarState(): Promise<{ available: boolean, opened: boolean }> {
      return (await this.handlerChain.process({
      type: 'crt.GetSidebarStateRequest',
      sidebarCode: SOME_SIDEBAR_CODE,
      $context: {}
      } as BaseRequest)) as { available: boolean, opened: boolean };
      }

      /* Check whether the sidebar is available. */
      private async _isSidebarAvailable(): Promise<boolean> {
      const sidebarState = await this._getSidebarState();
      return sidebarState.available;
      }

      /* Check whether the sidebar is open. */
      private async _isSidebarOpened(): Promise<boolean> {
      const sidebarState = await this._getSidebarState();
      return sidebarState.opened;
      }

      /* Refresh sidebar data when it is opened. */
      private async _refreshSidebarData(): Promise<void> {
      await this.handlerChain.process({
      type: 'usr.RefreshSomeSidebarDataRequest',
      $context: {}
      });
      }

      /* Handle the data sent by the web service. */
      private async _handleWebServiceEvent(): Promise<void> {
      /* Check whether the sidebar is open. */
      if (await this._isSidebarOpened()) {
      /* Refresh sidebar data. */
      await this._refreshSidebarData();
      } else {
      /* Open the sidebar when the web service sends required data. */
      await this._openSidebar();
      }
      }

      /* Subscribe to the data sent by the web service. When Creatio receives data, handle it. */
      private async _subscribeToWebServiceEvents(): Promise<void> {
      this._someService.getEventsObservable().then(() => {
      /* Handle the received data. */
      this._handleWebServiceEvent().then();
      });
      }

      public async handle(request: BaseRequest): Promise<void> {
      /* Check whether the sidebar is available. */
      if (await this._isSidebarAvailable()) {
      /* Wait for data sent by the web service. */
      this._checkUnreadMessages().then();
      /* Subscribe to the data sent by the web service. */
      this._subscribeToWebServiceEvents();
      }
      /* Call the next handler if it exists and return its result. */
      await this.next?.handle(request);
      }

      }
    8. Import the required functionality from the libraries into the class.

    9. Save the file.

  6. Register the handlers.

    1. Open the app.module.ts file.
    2. Add the OpenCloseSomeSidebarHandler and InitializeSomeSidebarHandler handlers to the requestHandlers section in the CrtModule decorator.
    3. Import the required functionality from the libraries into the class.
    4. Save the file.
    app.module.ts file
    /* Import the required functionality from the libraries. */
    import { CrtModule } from '@creatio-devkit/common';
    import { OpenCloseSomeSidebarHandler } from './open-close-some-sidebar.handler';
    import { InitializeSomeSidebarHandler } from './initialize-some-sidebar.handler';
    ...

    @CrtModule({
    ...,
    /* Specify that "OpenCloseSomeSidebarHandler" and "InitializeSomeSidebarHandler" are request handlers. */
    requestHandlers: [
    OpenCloseSomeSidebarHandler,
    InitializeSomeSidebarHandler
    ],
    })
    ...
  7. 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.

6. Add the implemented sidebar events to Creatio

Instructions: Add the custom UI component implemented using remote module to the Freedom UI page (steps 1–3).

As a result, Creatio will display the custom sidebar and handle the sidebar events implemented using remote module.


See also

Set up a sidebar (user documentation)

Manage an existing additional feature

Manage apps (user documentation)

Creatio IDE overview

Custom UI component implemented using remote module

Custom request handler implemented using remote module