Разработка и публикация клиентского компонента элемента управления

Клиентский компонент элемента управления — программный компонент, обеспечивающий загрузку и функционирование элемента управления на стороне клиента. Клиентский компонент предоставляет графический интерфейс элемента управления.

Клиентский компонент элемента управления является вариантом клиентского расширения.

Чтобы создать клиентский компонент элемента управления, выполните приведенную далее инструкцию.

  1. Создайте проект клиентского расширения. Не публикуйте его.

  2. Создайте в папке src файл TypeScript (.ts, .tsx) с кодом клиентского компонента.

    Клиентский компонент состоит из трёх блоков кода:
    1. Класс параметров:

      export class SuperControlParams extends BaseControlParams {
          @r firstProperty?: string;
          @rw secondProperty?: boolean;
      
          @apiEvent firstEvent?: BasicApiEvent<IEventArgs>;
      }

      Класс параметров является классом, расширяющим BaseControlParams. В данном классе перечисляются публичные свойства и события элемента управления, указанные в его описателе, которые отсутствуют в базовом классе BaseControlParams. В данном классе также перечисляются любые другие параметры, значение которых должно быть доступным извне.

      Если свойство, указанное в описателе, не требуется на клиентском уровне, его можно не объявлять в классе параметров.

      В приведенном выше коде объявляются два свойства и событие: firstProperty (строкового типа), secondProperty (булева типа) и firstEvent (событие).

      При объявлении свойства или события нужно указать декоратор:
      • @r — если свойство доступно только для чтения.

      • @rw — если свойство доступно для чтения и записи.

      • @apiEvent — если свойство является событием.

      Значение свойства будут загружено в поле, только если поле класса связано со свойством элемента управления.

      Чтобы поле класса могло быть связано со свойством элемента управления:
      • Имя поля класса должно совпадать с названием свойства/события элемента управления с условием.

        Первая буква в названии поля класса должна быть строчной. Например, если в описателе свойство называется SomeParam, то поле должно назваться someParam.

      • Тип поля класса должен совпадать с типом свойства элемента управления.

      Для событий должен быть установлен тип:
      • BasicApiEvent<IEventArgs> — для непрерываемых событий.

      • CancelableApiEvent<IEventArgs> — для прерываемых событий.

      Если в описателе элемента управления у свойства указано значение по умолчанию, данное значение должно быть указано в классе параметров.

    2. Интерфейс состояния:

       export interface SuperControlState extends SuperControlParams, BaseControlState {
       internalFirstState: boolean;
       }

      Интерфейс состояния является интерфейсом, расширяющим BaseControlParams.

      В данном интерфейсе перечисляются свойства, которые требуются для описания внутреннего состояния элемента управления (частные переменные).

      Если при работе элемента управления хранить внутреннее состояние не требуется, интерфейс состояния не будет содержать полей.

      export interface SuperControlState extends SuperControlParams, BaseControlState {
      }
    3. Класс реализации:

      export class SuperControlImpl extends BaseControlImpl<SuperControlParams, SuperControlState> {
          construct() { (1)
              super.construct();
      
              this.state.firstEvent = SimpleEvent.Create(this.state.wrapper);
          }
      
          renderControl() { (2)
              return (
                  <div />
              );
          }
      }
      1 Инициализация компонента.
      2 VirtualDOM элемента управления.

      Класс реализации является производным от контейнерного класса BaseControlImpl, в который передаются класс параметров и интерфейс состояния. Класс реализации возвращает виртуальный DOM, описывающий пользовательский интерфейс элемента управления.

      Класс реализации содержит два обязательных метода:
      construct

      В данном методе должны быть выполнены следующие действия:

      • Вызван конструктор базового класса с передачей ему публичных и внутренних свойств ЭУ:

        super.construct();
      • События, объявленные в классе параметров, должны быть проинициализированы, а внутренние обработчики событий связаны с текущим контекстом. Подробности в пункте Работа с событиями в клиентском компоненте.

      renderControl

      Метод должен вернуть VirtualDOM элемента управления.

      Пользовательский интерфейс элемента управления может быть сформирован с использован стандартных элементов React, стандартных элементов управления Web-клиента или разработанных элементов управления (см. дополнительные условия в пункте [Использование вложенных элементов управления](UseNestedControls.md)).

    4. Интерфейсный класс:

      export class SuperControl extends BaseControl<SuperControlParams, SuperControlState> {
          protected createParams() {
              return new SuperControlParams(); (1)
          }
      
          protected createImpl() { (2)
              return new SuperControlImpl(this.props, this.state);
          }
      }
      1 Инициализация параметров.
      2 Инициализация класса реализации.

      Интерфейсный класс является производным от контейнерного класса BaseControl, в который передаются класс параметров и интерфейс состояния.

      Интерфейсный класс обеспечивает жизненный цикл элемента управления: связывает элемент управления с его значением, инициализирует класс параметров, а также предоставляет проинициализированную сущность класса реализации.

      Интерфейсный класс должен содержать два обязательных метода:
      • createParams — метод должен вернуть экземпляр класса параметров;

      • createImpl — метод должен вернуть экземпляр класса реализации.

      Помимо указанных методов, интерфейсный класс может содержать функции, обрабатывающие загрузку значения свойства элемента управления с сервера Web-клиента.

      @handler("binding")
      private set Binding(binding: IBindingResult<boolean>) {
          this.state.readOnly = editOperationAvailable(this.state.services, binding) == false;
      }

    В случае простого элемента управления, лишенного сложной внутренней логики, реализация элемента управления может быть помещена в интерфейсный класс.

    export class SuperSimpleControl extends BaseControl<SuperControlParams, SuperControlState> {
        protected createParams() {
            return new SuperControlParams();
        }
    
        protected createImpl() { (1)
            return new ControlImpl(this.props, this.state, this.renderControl.bind(this));
        }
    
        renderControl() { (2)
            return (
                <div />
            );
        }
    }
    1 Метод createImpl в данном случае возвращает экземпляр стандартного типа ControlImpl, в которые передана функция, возвращающая VirtualDOM элемента управления
    2 Метод может иметь любое название, кроме "render".
  3. Измените содержимое файла Index.ts.

    import { extensionManager } from "@docsvision/webclient/System/ExtensionManager";
    
    import { SuperControl } from "./Controls/SuperControl"; (1)
    
    extensionManager.registerExtension({ (2)
        name: "Client extension with controls",
        version: "1.0",
        controls: [{ controlTypeName: "SuperControl", constructor: SuperControl }] (3) (4)
    })
    1 Добавьте строку импорта элемента управления.
    2 Добавьте в registerExtension поле controls, в значении которого укажите описание элемента управления.
    3 controlTypeName — название типа элемента управления, которое указано в описателе элемента управления
    4 constructor — интерфейсный класс элемента управления.
  4. Соберите проект клиентского расширения командой npm run build.

  5. Скопируйте полученный файл %BuildDir%\extension.js на сервер Web-клиента в папку \%WebCinstallDir%\5.5\Site\Content\Modules\%Каталог Решения%.

  6. После завершения отладки, соберите и опубликуйте на сервере Web-клиента "релизную версию" клиентского расширения. "Релизная версия" собирается командой npm run build:prod.