Перейти к содержимому
ФреймворкJavaScript

BlockAPI: работа с одним блоком

Интерфейс для работы с отдельными блоками. Возвращается методами blocks.getById(), blocks.getBlockByIndex() и blocks.insert().

Обновлено 7 окт. 2026 г.Редактировать на GitHub

Как получить экземпляр редактора

Методы ниже вызываются на редакторе, созданном через new Blok(). Они доступны после того, как разрешится editor.isReady.

TypeScript
// You already hold the instance returned by the constructor.
const editor = new Blok({ holder: 'editor' });
await editor.isReady;

// Call any API method on it.
editor.caret.setToLastBlock('end');

Методы

block.save()

Promise<void|SavedData>

Сохранить содержимое блока и вернуть его данные.

Когда использовать

Возвращает данные только этого блока. Используйте его, чтобы проверить или сохранить один блок без полного обхода, который делает editor.save().

TypeScript
const block = editor.blocks.getById('block-123');
const saved = await block.save();
// saved resolves to a SavedData object (or undefined if extraction fails):
// { id: 'block-123', tool: 'paragraph', data: { text: 'Block content' }, time: 1717000000000 }
console.log(saved?.data); // { text: 'Block content' }

block.validate(data)

Promise<boolean>

Проверить данные блока по правилам валидации инструмента.

Когда использовать

Запускает validate() инструмента для переданных данных. Используйте его, чтобы отсеять пустые или некорректные блоки перед сохранением.

TypeScript
const block = editor.blocks.getById('block-123');
const isValid = await block.validate({ text: 'Hello' });
if (!isValid) {
  console.log('Block data is invalid');
}

block.call(methodName, param?)

void

Вызвать собственный метод инструмента блока.

Когда использовать

Запасной способ вызвать собственный метод, который открывает ваш инструмент. Нужен для поведения вне стандартного API BlockTool.

TypeScript
const block = editor.blocks.getById('block-123');
// Call a custom method defined in the tool
block.call('showNotification', { message: 'Hello' });

block.dispatchChange()

void

Вручную вызвать колбэк onChange для этого блока.

Передайте { derived: true }, если изменение содержит данные, которые инструмент вычислил сам (измеренный размер, загруженное превью), а не правка пользователя. Оно сохраняется, но не добавляет шаг отмены и не сбрасывает повтор. Добавьте from с ключами данных, из которых оно вычислено ({ derived: true, from: ['url'] }): тогда оно входит в шаг отмены, который записал эти значения.

Когда использовать

Вызывайте его, когда меняете блок в обход Blok (например, асинхронно), чтобы сработали события изменения и синхронизация CRDT.

TypeScript
const block = editor.blocks.getById('block-123');
// Trigger change after invisible modification
block.dispatchChange();

block.getActiveToolboxEntry()

Promise<ToolboxConfigEntry | undefined>

Получить активный пункт тулбокса для этого блока (например, Заголовок 1 или Заголовок 2).

Когда использовать

Определяет, какой вариант в тулбоксе активен (например, Заголовок 1 или 2). Полезно, чтобы отражать состояние в своём UI.

TypeScript
const block = editor.blocks.getById('block-123');
const entry = await block.getActiveToolboxEntry();
if (entry) {
  console.log('Active entry:', entry.title);
}

block.getChildren()

BlockAPI[]

Прямые дочерние блоки этого блока как объекты BlockAPI, по порядку. Каждый BlockAPI, который выдаёт редактор, живой. Поэтому возвращённые дочерние блоки можно обходить рекурсивно (child.getChildren()) и изменять (child.setParent(...), child.insertChild(...)).

TypeScript
const block = editor.blocks.getById('toggle-123');
block?.getChildren().forEach((child) => console.log(child.id));

block.setParent(parentId)

void

Переподчинить этот блок родителю parentId или вернуть его на корневой уровень значением null. Вызов идёт через единую точку ядра setBlockParent, поэтому contentIds родителя обновляется вместе с parentId этого блока.

TypeScript
const block = editor.blocks.getById('block-123');
block?.setParent('parent-block-id');

// Back to the root level
block?.setParent(null);

block.insertChild(childData?, position?, toolName?, options?)

BlockAPI

Вставить дочерний блок под ЭТОТ блок атомарно. Создание и назначение родителя укладываются в один шаг отмены (вызов делегируется в blocks.insertInsideParent).

  • position принимает BlockChildPosition: 'start' | 'end' | { before: childId } | { after: childId }.
    • По умолчанию это 'end': блок добавляется в конец, за всё поддерево.
  • toolName выбирает блочный инструмент дочернего блока и по умолчанию равен config.defaultBlock. Поэтому ТИПИЗИРОВАННЫЙ дочерний блок создаётся одной операцией, а не вставкой с последующим переподчинением.
    • Инструмент, ограниченный внутри ячеек таблицы, понижается до блока по умолчанию, если новый дочерний блок попал бы внутрь такой ячейки.
  • childData по умолчанию равен { text: '' } для блока по умолчанию и {}, когда toolName называет другой инструмент.
  • options использует тот же словарь { focus, caret, id, tunes, replace }, что и расширенная спецификация insert у адаптеров фреймворков.

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

Параметры

ПараметрТипОбязательныйПо умолчаниюОписание
childDataBlockToolData—{ text: '' } / {}

Данные для нового дочернего блока. По умолчанию это пустой объект данных параграфа для блочного инструмента по умолчанию. Если указан toolName, по умолчанию будет {}, и инструмент применит собственные значения по умолчанию.

positionBlockChildPosition—'end'

Куда среди существующих дочерних блоков вставлять: 'start', 'end', { before: childId } или { after: childId }.

toolNamestring—config.defaultBlock

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

optionsInsertChildOptions—{}

focus делает новый дочерний блок текущим. caret ставит курсор внутрь него ({ position?, offset? }) и срабатывает, только когда дочерний блок действительно создан.

id задаёт явный id. Уже существующий id работает как «вставить, если нет»: возвращается этот дочерний блок, ничего не создаётся.

tunes задаёт данные тюнов блока, применяемые при создании. replace перезаписывает дочерний блок, названный объектной позицией, вместо вставки рядом с ним. С 'start' или 'end' перезаписывать нечего, поэтому вызов выбрасывает исключение.

TypeScript
const block = editor.blocks.getById('toggle-123');
const child = block?.insertChild({ text: 'Hidden content' });

// Place it among the existing children instead of appending
block?.insertChild({ text: 'First' }, 'start');
block?.insertChild({ text: 'After that one' }, { after: 'child-id' });

// A typed child, in a single undo entry
block?.insertChild({ text: 'Section', level: 3 }, 'end', 'header');

// Drop the caret into the new child at a specific offset
block?.insertChild({ text: 'Draft' }, 'end', undefined, { caret: { offset: 5 } });

// Idempotent: a re-running effect cannot duplicate this child
block?.insertChild({ text: 'Intro' }, 'start', undefined, { id: 'intro-row' });

// Child-level "turn into" — overwrite an existing child, keeping it parented
block?.insertChild({ text: 'Now a heading', level: 3 }, { before: 'child-id' }, 'header', { replace: true });

block.moveChild(childId, delta)

void

Переместить прямой дочерний блок на delta позиций среди его соседей, с ограничением по допустимому диапазону. Дочерний блок со своим поддеревом встаёт за потомками целевого соседа, а не внутрь них. Ничего не происходит, когда delta равна 0, когда childId не является прямым дочерним блоком или когда ограниченное перемещение не изменит позицию.

TypeScript
const block = editor.blocks.getById('toggle-123');
block?.moveChild('child-id', -1); // one position toward the start
block?.moveChild('child-id', 1);  // one position toward the end

Свойства

СвойствоТипОписание
idstring

Уникальный идентификатор блока

namestring

Имя инструмента (например, «paragraph», «header»)

configToolConfig

Конфигурация инструмента, переданная при инициализации

holderHTMLElement

Обёртка HTML-элемента инструмента

isEmptyboolean

True, если содержимое блока пусто

selectedboolean

True, если блок входит в выбор на уровне БЛОКОВ (перетаскивание рамкой, Shift+Click, Shift+Arrow, Cmd/Ctrl+A). Перетаскивание по тексту нескольких блоков даёт вместо этого выделение на уровне символов. При нём ни один блок не помечен как выбранный, поэтому такое выделение читайте из собственного Selection документа.

focusableboolean

True, если у блока есть поля ввода, которые можно сфокусировать

stretchedboolean

Геттер/сеттер состояния растягивания блока

parentIdstring | null

Id родительского блока или null, если у этого блока нет родителя

contentIdsreadonly string[]

Id прямых дочерних блоков этого блока, по порядку. Это копия только для чтения, поэтому её изменение ничего не даёт. Это аналог parentId на уровне блока: он позволяет контейнерному инструменту читать свои дочерние блоки, не обращаясь к API редактора

preservedDataBlockToolData

Последние успешно извлечённые данные блочного инструмента. Значение синхронное, поэтому помогает, когда асинхронный save() неприменим, например при операциях с буфером обмена.

Это внутренний снимок, поэтому поля с форматированным текстом здесь остаются HTML-строками. save() возвращает их как фрагменты.

preservedTunes{ [name: string]: BlockTuneData }

Последние успешно извлечённые данные тюнов блока. Значение синхронное, поэтому помогает, когда асинхронный save() неприменим, например при операциях с буфером обмена