BlockAPI: работа с одним блоком
Интерфейс для работы с отдельными блоками. Возвращается методами blocks.getById(), blocks.getBlockByIndex() и blocks.insert().
Как получить экземпляр редактора
Методы ниже вызываются на редакторе, созданном через new Blok(). Они доступны после того, как разрешится editor.isReady.
// 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().
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() инструмента для переданных данных. Используйте его, чтобы отсеять пустые или некорректные блоки перед сохранением.
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.
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.
const block = editor.blocks.getById('block-123');
// Trigger change after invisible modification
block.dispatchChange();block.getActiveToolboxEntry()
Promise<ToolboxConfigEntry | undefined>Получить активный пункт тулбокса для этого блока (например, Заголовок 1 или Заголовок 2).
Когда использовать
Определяет, какой вариант в тулбоксе активен (например, Заголовок 1 или 2). Полезно, чтобы отражать состояние в своём UI.
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(...)).
const block = editor.blocks.getById('toggle-123');
block?.getChildren().forEach((child) => console.log(child.id));block.setParent(parentId)
voidПереподчинить этот блок родителю parentId или вернуть его на корневой уровень значением null. Вызов идёт через единую точку ядра setBlockParent, поэтому contentIds родителя обновляется вместе с parentId этого блока.
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, чтобы применить тюны.
Параметры
| Параметр | Тип | Обязательный | По умолчанию | Описание |
|---|---|---|---|---|
childData | BlockToolData | — | { text: '' } / {} | Данные для нового дочернего блока. По умолчанию это пустой объект данных параграфа для блочного инструмента по умолчанию. Если указан toolName, по умолчанию будет {}, и инструмент применит собственные значения по умолчанию. |
position | BlockChildPosition | — | 'end' | Куда среди существующих дочерних блоков вставлять: 'start', 'end', { before: childId } или { after: childId }. |
toolName | string | — | config.defaultBlock | Блочный инструмент, который нужно создать для дочернего блока. Он понижается до блока по умолчанию, если ограничен внутри ячеек таблицы и новый дочерний блок попал бы внутрь такой ячейки. |
options | InsertChildOptions | — | {} | focus делает новый дочерний блок текущим. caret ставит курсор внутрь него ({ position?, offset? }) и срабатывает, только когда дочерний блок действительно создан. id задаёт явный id. Уже существующий id работает как «вставить, если нет»: возвращается этот дочерний блок, ничего не создаётся. tunes задаёт данные тюнов блока, применяемые при создании. replace перезаписывает дочерний блок, названный объектной позицией, вместо вставки рядом с ним. С 'start' или 'end' перезаписывать нечего, поэтому вызов выбрасывает исключение. |
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 не является прямым дочерним блоком или когда ограниченное перемещение не изменит позицию.
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Свойства
| Свойство | Тип | Описание |
|---|---|---|
id | string | Уникальный идентификатор блока |
name | string | Имя инструмента (например, «paragraph», «header») |
config | ToolConfig | Конфигурация инструмента, переданная при инициализации |
holder | HTMLElement | Обёртка HTML-элемента инструмента |
isEmpty | boolean | True, если содержимое блока пусто |
selected | boolean | True, если блок входит в выбор на уровне БЛОКОВ (перетаскивание рамкой, Shift+Click, Shift+Arrow, Cmd/Ctrl+A). Перетаскивание по тексту нескольких блоков даёт вместо этого выделение на уровне символов. При нём ни один блок не помечен как выбранный, поэтому такое выделение читайте из собственного Selection документа. |
focusable | boolean | True, если у блока есть поля ввода, которые можно сфокусировать |
stretched | boolean | Геттер/сеттер состояния растягивания блока |
parentId | string | null | Id родительского блока или null, если у этого блока нет родителя |
contentIds | readonly string[] | Id прямых дочерних блоков этого блока, по порядку. Это копия только для чтения, поэтому её изменение ничего не даёт. Это аналог parentId на уровне блока: он позволяет контейнерному инструменту читать свои дочерние блоки, не обращаясь к API редактора |
preservedData | BlockToolData | Последние успешно извлечённые данные блочного инструмента. Значение синхронное, поэтому помогает, когда асинхронный save() неприменим, например при операциях с буфером обмена. Это внутренний снимок, поэтому поля с форматированным текстом здесь остаются HTML-строками. |
preservedTunes | { [name: string]: BlockTuneData } | Последние успешно извлечённые данные тюнов блока. Значение синхронное, поэтому помогает, когда асинхронный save() неприменим, например при операциях с буфером обмена |