Getting Started
Overview
Installation
Theme
Forms
Basic Inputs
Custom Inputs
Select
Components
Components
78
Micro Charts
Navigation
Libraries
Content Editor
Data View
Form Builder
Headless Editor
Image Designer
Kanban Board
PDF Builder
PDF Signer
PDF Viewer
Video Player
GitHub repositoryGitHub starsGitHub forksNgStarter UI npm versionNgStarter UI npm downloads per month

Blocks

Blocks are the top-level units of a document. Plugins register block types; the document stores only the type name and data, and the definition decides how the block is rendered and edited.

Loading example…

Block definitions

const documentBlocksPlugin = defineNgsHeadlessEditorPlugin({
  id: 'document-blocks',
  blocks: [
    {
      type: 'heading',
      tagName: 'h3',
      create: () => createNgsHeadlessEditorParagraph()   // Enter leaves the heading
    },
    {
      type: 'bulletItem',
      tagName: 'ul',
      contentTagName: 'li',
      create: () => ({ ...createNgsHeadlessEditorParagraph(), type: 'bulletItem' })
    },
    {
      type: 'divider',
      tagName: 'div',
      editable: false,
      create: createDivider,
      render: element => element.append(element.ownerDocument.createElement('hr')),
      isEmpty: () => false
    }
  ]
});
MemberDescription
typeUnique block type stored in the document.
tagNameElement that represents the block.
contentTagNameOptional nested element that holds the text, for example ul with li or pre with code.
editableSet to false for atomic blocks the browser must not edit.
create()Creates an empty block of this type. Enter in a non-empty block uses it for the block that follows: return a paragraph to leave the type after one Enter (headings), or the same type to continue it (quotes, list items, code lines).
exitOnEmptyEnterEnter in an empty block of this type replaces the empty line with a block of exitType, so pressing Enter twice leaves a quote, list, or code block. Defaults to true for text blocks; set false to keep creating empty blocks.
exitTypeBlock type used when leaving. Defaults to paragraph.
render(element, block)Optional custom rendering into the block element, for atomic or non-text blocks.
read(element, previous)Optional parser used when browser-owned DOM of this block is read back.
isEmpty(block)Optional. Atomic blocks usually return false so a document that contains them is not considered empty.
editorComponent, rendererComponentAngular components that render the block. See Component Blocks.

The paragraph type comes from basicTextEditorPlugin(). Blocks without a registered definition are rendered as div elements.

Text blocks are lines

Every text block holds one line. Lists, quotes, and code are sequences of blocks of the same type, which keeps the model flat and the operations simple. Style consecutive blocks so they read as one list or one code listing, for example by removing margins between adjacent ul elements.

Leaving a block

The first Enter at the end of a quote, list item, or code line continues the block with the type returned by create(). A second Enter on the resulting empty line removes it and puts the caret in a new paragraph below the block. The exit is one undo step. Headings leave after a single Enter because their create() returns a paragraph.

{
  type: 'blockquote',
  tagName: 'blockquote',
  create: () => ({ ...createNgsHeadlessEditorParagraph(), type: 'blockquote' }),
  // exitOnEmptyEnter: true,   default: Enter on an empty quote line leaves the quote
  // exitType: 'paragraph'     default: what the empty line becomes
}

Block operations

editor.toggleBlock('heading');
editor.isBlockActive('bulletItem');
editor.insertBlock({ id: createNgsHeadlessEditorId('divider'), type: 'divider', content: null });
editor.updateBlock(blockId, { attrs: { level: 2 } });
editor.removeBlock(blockId);
MethodDescription
toggleBlock(type, fallback?)Switches the selected blocks to a type, or back to the fallback (paragraph) when all of them already have it. Text and marks are kept.
isBlockActive(type)True when every selected block has the type.
insertBlock(block, select?)Inserts a block after the block that holds the caret.
updateBlock(id, patch, origin?)Replaces type, content, or attrs of a block by id. Recorded in history.
removeBlock(id)Removes a block; an empty paragraph is created if it was the last one.
splitBlock()Splits the text block at the caret, like Enter.

Atomic blocks

Atomic blocks have non-text content and are handled as a unit: Backspace at the start of the next text block or Delete at the end of the previous one removes them, and a selection that crosses them removes them when it is replaced. A selection that only ends at an atomic block keeps it.

function createDivider(): NgsHeadlessEditorBlock<null> {
  return { id: createNgsHeadlessEditorId('divider'), type: 'divider', content: null };
}

const image: NgsHeadlessEditorBlock<null> = {
  id: createNgsHeadlessEditorId('image'),
  type: 'image',
  content: null,
  attrs: { src: '/assets/chart.png', alt: 'Revenue chart' }
};