Архитектура
Скрипт представляет собой исполняемый JavaScript-код, который подписывается на события изменения полей формы и задает логику вычисления зависимых полей. Рассмотрим пример:
Есть форма с полями «Цена единицы товара», «Количество» и «Общая сумма». Поле «Общая сумма» можно заполнять автоматически (как произведение цены на количество) с помощью следующего кода:
form .onChange(['Цена единицы товара', 'Количество']) .setValue('Общая сумма', state => { const [price, quantity] = state.changes; if (!price || !quantity) return null; return price.value * quantity.value; });
Разберем подробнее этот код.
В контексте исполнения скрипта доступен глобальный объект form типа FormProxy, обеспечивающий взаимодействие кода скрипта с формой в Pyrus:
interface FormProxy { onChange(fieldNames: string[]): ChangeHandler; fetchSelfRegister( filterFn: (filter: RegisterFilter) => RegisterFilter, fieldNames: string[] ): Promise<RegisterResponse>; getDateWithTimezoneOffset(date: string): Date; }
Подсказка: функция getDateWithTimezoneOffset
преобразует переданное значение поля типа Дата в значение, в котором учтено смещение по часовому поясу.
Метод onChange
принимает первым аргументом массив названий полей формы (Цена единицы товара и Количество), при изменении которых нужно вычислить значения зависимых полей, и возвращает объект типа ChangeHandler.
Метод onChange
вызывается при изменении любого из полей, упомянутых в первом параметре. Результатом работы скрипта является заполнение зависимых полей или валидация. Но иногда этот процесс нарушается. Например, если значения исходных полей заполняются методами API, с помощью бота или клиентского приложения, которое не поддерживает скрипты, то в нужный момент скрипт не сработает и зависимые поля не заполнятся.
В этом случае при настройке onChange
следует указать второй параметр true
. Благодаря ему скрипт будет запускаться не только при изменении указанных полей, но и каждый раз при входе в задачу (если параметр не указан как true
, то по умолчанию он считается false
). Настройка работает так: при первом входе пользователя в задачу после заполнения исходных полей через веб-браузер или другой клиент Pyrus с поддержкой скриптов, скрипт выполняется, то есть зависимые поля заполняются и/или валидация производится.
Подробнее про метод fetchSelfRegister
см. Реестр формы.
ChangeHandler позволяет задать логику вычисления зависимых полей (Общая сумма), которая будет выполняться каждый раз при изменении любого из полей, перечисленных в методе onChange
.
interface ChangeHandler { setValue( fieldName: string, calcFunction: (state: FormState) => CompositeValue ): void; setValues( fieldNames: string[], calcFunction: (state: FormState) => CompositeValue[] ): void; setValueAsync( fieldName: string, calcFunction: (state: FormState) => Promise<CompositeValue> ): void; setValuesAsync( fieldNames: string[], calcFunction: (state: FormState) => Promise<CompositeValue[]> ): void; validate( fieldName: string, validateFunction: (state: FormState) => {errorMessage: string} | null ): void; validateAsync( fieldName: string, validateFunction: (state: FormState) => Promise<{errorMessage: string} | null> ): void; }
Аргументы метода setValue
:
fieldName
— название поля, значение которого нужно вычислитьcalcFunction
— функция вычисления значения поля.
Функция calcFunction
получает на вход единственным аргументом объект типа FormState и возвращает новое значение (см. Формат значений полей) вычисленного поля, объявленного в методе setValue
.
Для случаев, когда нужно вычислить сразу несколько полей на основе одних и тех же данных, удобно воспользоваться методом setValues
— он принимает массив имен полей, а calcFunction
в этом случае должна вернуть соответствующий массив значений этих полей.
Если для вычислений требуется произвести асинхронные операции (например, дождаться завершения запроса реестра или загрузки справочника), воспользуйтесь асинхронными версиями методов: setValueAsync
и setValuesAsync
. Их отличие в том, что в calcFunction
возвращается Promise («обещание»), который вернет значения полей. Пример использования приведен в разделе Реестр формы.
Методы validate
и validateAsync
позволяют реализовать гибкую валидацию заполнения формы и отображение ошибок. Подробнее см. Валидация.
Объект FormState позволяет получить значения зависимых полей (Цена единицы товара и Количество), на основе которых вычисляется значение поля «Общая сумма»:
interface FormState { changes: FieldValue[]; prev: FieldValue[]; }
Поле changes
содержит массив текущих значений полей, перечисленных в методе onChange
. Поле prev
содержит массив «предыдущих» значений вычисляемых полей.