Скрипты в виджетах

Виджеты — это один из базовых элементов построения интерфейса. Виджеты могут создаваться и быть доступны в рамках раздела или приложения, а также быть общими для всей компании. Подробнее о виджетах можно узнать в статье «Создание интерфейсов».

Для выполнения кода, который может осуществлять сложную логику работы с объектами системы или управлять данными и внешним видом виджета, используются скрипты. Код скрипта может представлять собой набор функций, пользовательских классов, интерфейсов, написанных на языке TypeScript.

По назначению исполнения скрипты в виджетах делятся на:

  • Клиентские — исполняются в браузере клиента, ограничены правами пользователя, под которым запускаются;

  • Серверные — исполняются на сервере с правами администратора, но имеют ограничение по количеству выполняемых функций в минуту.

Доступ к данным. Роли виджетов

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

Общие виджеты

Общими виджетами называются виджеты, созданные в разделе Администрирование / Интерфейсы и доступные из всех разделов компании. При этом общий виджет имеет только собственный контекст, который содержит свойства, добавленные на вкладке Контекст в конструкторе данного виджета, а также системные свойства, код которых начинается с двойного подчеркивания. Доступ к таким свойствам в скриптах осуществляется с помощью константы Context.

    Context.data.string_1 = 'string value';

Виджеты уровня раздела и приложения

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

Виджеты можно использовать многократно: один виджет можно добавить в один или несколько других виджетов без ограничения вложенности. Таким образом можно составлять сложные интерфейсы. При этом в скрипте каждого виджета все так же доступны свойства только его собственного контекста и недоступны свойства из контекста дочерних виджетов.

Виджеты форм

Для приложений и бизнес-процессов могут быть созданы пользовательские формы. Для каждой пользовательской формы автоматически создается самостоятельный виджет, который закрепляется за этой формой. Виджеты форм тоже имеют основной контекст Context, но он содержит свойства того объекта, формой которого является данный виджет. Например, если виджет является формой приложения, то в контексте ему доступны свойства данного приложения. То же самое для форм в процессах: в их виджетах доступны свойства контекста бизнес-процесса.

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

    const itemName = Context.data.__name;
    ViewContext.data.string_1 = `Название ${ itemName }}`;

Функции

Скрипты в виджетах представляют собой набор функций. При загрузке виджета загружаются и транслируются (преобразуются) в JavaScript-скрипты, формируется контекст. Непосредственный запуск (исполнение) конкретных функций происходит по отдельности в момент вызова.

Системные функции

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

  • Инициализация — функция, запускаемая при инициализации виджета. Может быть использована для инициализации стартовых значений свойств контекста, получения необходимых данных, определения внешнего вида виджета при загрузке, а также запуска других функций при загрузке виджета.

Пример использования:

async function onInit (): Promise<void> {
    Context.data.counter = 0;
    setStartValues();
}
  • Необходимость отображения — функция, запускаемая перед рендером виджета и определяющая, будет ли он отображен. Функция должна возвращать значение типа boolean. Если функция возвращает false, то рендер виджета отменяется.

Пример использования:

async function canRender (): Promise<void> {
    return !!Context.data.app;
}
  • Валидация — пользовательская функция валидации. Запускается формой создания или редактирования при сохранении элемента приложения вместе со стандартной валидацией формы. Функция должна возвращать объект результата валидации типа ValidationResult. Если данный объект не будет содержать ошибок, то пользовательская валидация будет считаться успешной и сохранение или изменение элемента будет продолжено. Если объект будет содержать хотя бы одно сообщение об ошибке, то сохранение или изменение будет прервано. Функция валидации запускается в основном виджете формы, а также по всем вложенным виджетам, если у них описана функция валидации. Результаты валидации всех виджетов суммируются и показываются на форме.

Пример использования:

async function validation (): Promise<ValidationResult> {
    const result = new ValidationResult();
    if (!Context.data.stroka || Context.data.stroka.length < 10) {
        result.addContextError('stroka', 'Значение должно быть длиной не менее 10 символов');
    }
    return result;
}

Пользовательские функции

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

async function onInit (): Promise<void> {
    const result = getValues();
    ...
}

function getValues (): Promise<any> {
    return {
        property_1: Context.data.prop1,
        property_2: `some string`,
    };
}

Вызов серверной функции из клиентского скрипта

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

Серверная функция:

async function DoSomeWork() : Promise<void> {
    // Здесь задана обычная логика серверного скрипта
    // Можно также использовать внешние вызовы через `await`
    let response = await fetch('https://my-service.mycompany.com/getmydata?token=' + Context.data.secureToken);
    Context.data.mySecureData = await response.text();
}

Клиентская функция:

async function onButtonClick() : Promise<void> {
    ViewContext.data.blockUI = true;
    await Server.rpc.DoSomeWork();
    ViewContext.data.blockUI = false;
}

Вызов функции дочерними виджетами

Помимо перечисленных, удобным вариантом вызова функций является вызов с помощью вложенных виджетов. Например, если добавить виджет Кнопка и выбрать в её настройках тип действия Скрипт, то в поле Выполняемый скрипт можно будет выбрать необходимую функцию.

Здесь мы можем выбрать тип функции (Клиент или Сервер), а затем выбрать функцию из предлагаемого списка.

Свойства, позволяющие вызвать функцию, у разных виджетов могут отличаться. Например, у виджета Вкладки есть Событие при переключении вкладки. Также у всех виджетов есть системные события: Событие при наведении курсора и Событие при перемещении курсора за границы. Как правило, все подобные свойства находятся на вкладке События в настройках виджета.

Вызов из виджета «Код»

Для вызова клиентского скрипта из виджета Код можно использовать конструкцию <%= Scripts %>.ИМЯ_ФУНКЦИИ():

    <button onclick="<%= Scripts%>.OpenPopup()">open popup</button>

Используя вызов функции из скриптов в атрибуте элемента, например onclick, можно передать только строку, но не какой-либо объект целиком. Например:

    <button onclick="<%= Scripts%>.check('<%= someObject.__id %>')">Выполнить</button>

Вызов функции в файле виджета

Для виджетов есть возможность загружать файлы. Если загрузить в виджет файл с JS-кодом, то можно вызвать функцию из файла. Для этого необходимо в виджете Код подключить JS-файл из файлов виджета. Например:

    <script type="text/javascript" src="<%= UI.widget.filePath %>/test2.js"></script>
    <button type="button" onclick="onClickAction()">Кнопка</button>