Поле JS

Введение

Поле JS используется для пользовательской отрисовки содержимого в позиции поля с помощью JavaScript. Обычно применяется в блоках «Детали», в элементах формы только для чтения или как «прочие пользовательские элементы» в столбцах таблицы. Подходит для индивидуального отображения: сводная вычисляемая информация, индикаторы статусов, форматированный текст или диаграммы.

jsfield-readonly-add-20251029

Типы

  • Только для чтения: используется для отображения без редактирования; читает ctx.value, чтобы отрисовать результат.
  • Редактируемое: используется для пользовательской логики ввода. Доступны ctx.getValue() / ctx.setValue(v) и контейнерное событие js-field:value-change для двусторонней синхронизации со значениями формы.

Сценарии использования

  • Только для чтения

    • Блок «Детали»: отображение только для чтения — например, результаты вычислений, индикаторы статусов, фрагменты форматированного текста, диаграммы и т. д.
    • Блок «Таблица»: используется как «Другая пользовательская колонка» → «Поле JS» для режима только для чтения (если нужен столбец без привязки к полю коллекции, используйте колонку JS).
  • Редактируемое

    • Блок формы (создание или редактирование записи): пользовательские элементы ввода или составные поля ввода, которые проходят валидацию и отправляются вместе с формой.
    • Подходит для сценариев вроде: полей ввода из внешних библиотек, форматированного текста и редакторов кода, сложных динамических компонентов и т. д.

API контекста выполнения

Код поля JS может напрямую использовать следующие возможности контекста:

  • ctx.element: контейнер DOM поля (ElementProxy), поддерживает innerHTML, querySelector, addEventListener и т.д.
  • ctx.value: текущее значение поля (только для чтения).
  • ctx.record: текущий объект записи (только для чтения).
  • ctx.collection: метаданные коллекции, к которой относится поле (только для чтения).
  • ctx.requireAsync(url): асинхронная загрузка библиотеки в формате AMD или UMD по URL.
  • ctx.importAsync(url): динамический импорт модуля в формате ES-модулей по URL.
  • ctx.openView(options): открывает настроенный элемент просмотра (всплывающее окно, выдвижной блок или страницу).
  • ctx.i18n.t() / ctx.t(): функции интернационализации.
  • ctx.onRefReady(ctx.ref, cb): вызывает отрисовку после готовности контейнера.
  • ctx.libs.React / ctx.libs.ReactDOM / ctx.libs.antd / ctx.libs.antdIcons / ctx.libs.dayjs / ctx.libs.lodash / ctx.libs.math / ctx.libs.formula: встроенные библиотеки React, ReactDOM, Ant Design, иконки Ant Design, dayjs, lodash, math.js и formula.js для разметки на JSX, работы с датой и временем, обработки данных и вычислений. (ctx.React / ctx.ReactDOM / ctx.antd сохранены для совместимости.)
  • ctx.render(vnode): отрисовывает элемент на React, строку разметки HTML или узел дерева документа в контейнер по умолчанию ctx.element. Повторный вызов снова использует корень и перезаписывает содержимое контейнера.

Особенности редактируемого типа (JSEditableField):

  • ctx.getValue(): возвращает текущее значение формы (приоритет: состояние формы, затем свойства поля).
  • ctx.setValue(v): задаёт значение формы и свойства поля, сохраняя двустороннюю синхронизацию.
  • контейнерное событие js-field:value-change: срабатывает при изменении внешнего значения; упрощает обновление отображения поля ввода из сценария.

Редактор и сниппеты

Редактор сценариев для поля JS поддерживает подсветку синтаксиса, подсказки по ошибкам и встроенные сниппеты кода.

  • Сниппеты: открывает список встроенных сниппетов — можно искать и вставлять их в позицию курсора одним щелчком.
  • Запуск: выполняет текущий код напрямую. Вывод выполнения показывается на панели Журнал внизу; поддерживаются вызовы console.log, console.info, console.warn, console.error и подсветка ошибок для удобного поиска по месту.

jsfield-readonly-toolbars-20251029

Также можно генерировать код с помощью ИИ-сотрудника:

Типовое использование

1) Базовый рендеринг (чтение значения поля)

ctx.render(<span className="nb-js-field">{String(ctx.value ?? '')}</span>);

2) Использование JSX для рендеринга React-компонента

const { Tag } = ctx.libs.antd;
ctx.render(
  <div style={{ padding: 4 }}>
    <Tag color={ctx.value ? 'green' : 'default'}>{String(ctx.value ?? '')}</Tag>
  </div>
);

3) Загрузка сторонних библиотек (AMD, UMD или ES-модули)

// AMD/UMD
const dayjs = await ctx.requireAsync('https://cdn.jsdelivr.net/npm/dayjs@1/dayjs.min.js');
ctx.render(<span>{dayjs().format('YYYY-MM-DD HH:mm')}</span>);

// ES-модули
const { default: he } = await ctx.importAsync('https://cdn.jsdelivr.net/npm/he/+esm');
ctx.render(<span>{he.encode(String(ctx.value ?? ''))}</span>);

4) Щелчок для открытия всплывающего окна или выдвижного блока (openView)

ctx.element.innerHTML = `<a class="open-detail">Подробности</a>`;
const a = ctx.element.querySelector('.open-detail');
const tk = ctx.collection?.getFilterByTK?.(ctx.record);
a?.addEventListener('click', async () => {
  await ctx.openView('target-view-uid', {
    navigation: false,
    mode: 'drawer',
    dataSourceKey: ctx.collection?.dataSourceKey,
    collectionName: ctx.collection?.name,
    filterByTk: tk,
  });
});

5) Редактируемое поле ввода (JSEditableFieldModel)

// Отрисовываем простое поле ввода на JSX и синхронизируем значение с формой
function InputView() {
  return (
    <input
      className="nb-js-editable"
      style={{ width: '100%', padding: '4px 8px' }}
      defaultValue={String(ctx.getValue() ?? '')}
      onInput={(e) => ctx.setValue(e.currentTarget.value)}
    />
  );
}

// Синхронизируем поле ввода при изменении внешнего значения (по желанию)
ctx.element.addEventListener('js-field:value-change', (ev) => {
  const el = ctx.element.querySelector('.nb-js-editable');
  if (el) el.value = ev.detail ?? '';
});

ctx.render(<InputView />);

Примечания

  • Рекомендуется использовать доверенную сеть доставки контента для загрузки внешних библиотек и предусмотреть запасной сценарий на случай ошибок (например, if (!lib) return;).
  • Рекомендуется использовать селекторы по атрибуту class или [name=...] вместо фиксированных id, чтобы избежать дублирования идентификаторов в разных блоках или модальных окнах.
  • Очистка событий: поле может перерисовываться несколько раз из-за изменения данных или смены вида. Перед привязкой обработчика очищайте подписки или исключайте дубликаты, чтобы избежать повторных срабатываний.