Lexical provides various utility functions for common operations. These functions typically start with $ and must be called within editor.update() or editor.read().
Node Utilities
$getRoot
function $getRoot(): RootNode
Returns the root node of the editor.
editor.update(() => {
const root = $getRoot();
console.log(root.getChildrenSize());
});
$getNodeByKey
function $getNodeByKey<T extends LexicalNode>(key: NodeKey): T | null
Returns the node with the given key.
The node or null if not found
editor.update(() => {
const node = $getNodeByKey('abc123');
if (node) {
console.log(node.getType());
}
});
$getNodeByKeyOrThrow
function $getNodeByKeyOrThrow<T extends LexicalNode>(key: NodeKey): T
Returns the node with the given key or throws if not found.
$getNearestNodeFromDOMNode
function $getNearestNodeFromDOMNode(dom: Node): LexicalNode | null
Finds the Lexical node associated with a DOM node.
The associated Lexical node
$nodesOfType
function $nodesOfType<T extends LexicalNode>(klass: Klass<T>): Array<T>
Returns all nodes of a specific type in the editor state.
import { $nodesOfType, TextNode } from 'lexical';
editor.update(() => {
const textNodes = $nodesOfType(TextNode);
console.log(`Found ${textNodes.length} text nodes`);
});
Node Type Checks
$isRootNode
function $isRootNode(node: LexicalNode | null | undefined): node is RootNode
Returns true if the node is a RootNode.
$isTextNode
function $isTextNode(node: LexicalNode | null | undefined): node is TextNode
Returns true if the node is a TextNode.
$isElementNode
function $isElementNode(node: LexicalNode | null | undefined): node is ElementNode
Returns true if the node is an ElementNode.
$isDecoratorNode
function $isDecoratorNode<T>(node: LexicalNode | null | undefined): node is DecoratorNode<T>
Returns true if the node is a DecoratorNode.
$isRootOrShadowRoot
function $isRootOrShadowRoot(node: LexicalNode | null | undefined): boolean
Returns true if the node is a root or shadow root.
$isLeafNode
function $isLeafNode(node: LexicalNode | null | undefined): boolean
Returns true if the node is a leaf node (TextNode, LineBreakNode, or DecoratorNode).
Node Creation
$createTextNode
function $createTextNode(text?: string): TextNode
Creates a new TextNode.
$createParagraphNode
function $createParagraphNode(): ParagraphNode
Creates a new ParagraphNode.
$createLineBreakNode
function $createLineBreakNode(): LineBreakNode
Creates a new LineBreakNode.
$createTabNode
function $createTabNode(): TabNode
Creates a new TabNode.
Node Manipulation
$copyNode
function $copyNode<T extends LexicalNode>(node: T): T
Creates a deep copy of a node.
$cloneWithProperties
function $cloneWithProperties<T extends LexicalNode>(node: T): T
Clones a node preserving all properties.
$applyNodeReplacement
function $applyNodeReplacement<T extends LexicalNode>(node: T): T
Applies any registered node replacements.
$splitNode
function $splitNode(node: ElementNode, offset: number): [ElementNode | null, ElementNode]
Splits an ElementNode at the specified offset.
The child index to split at
nodes
[ElementNode | null, ElementNode]
Array of [left, right] nodes after split
Node Relationships
$findMatchingParent
function $findMatchingParent(
node: LexicalNode,
findFn: (node: LexicalNode) => boolean
): LexicalNode | null
Finds the nearest ancestor matching a condition.
findFn
(node: LexicalNode) => boolean
required
Function to test each ancestor
The matching ancestor or null
const listItem = $findMatchingParent(node, (n) => $isListItemNode(n));
$hasAncestor
function $hasAncestor(
child: LexicalNode,
targetNode: LexicalNode
): boolean
Returns true if targetNode is an ancestor of child.
$getNearestRootOrShadowRoot
function $getNearestRootOrShadowRoot(node: LexicalNode): RootNode | ElementNode
Returns the nearest root or shadow root ancestor.
Editor Context
$getEditor
function $getEditor(): LexicalEditor
Returns the active editor instance.
editor.update(() => {
const editor = $getEditor();
console.log(editor.getKey());
});
$addUpdateTag
function $addUpdateTag(tag: string): void
Adds a tag to the current update.
$hasUpdateTag
function $hasUpdateTag(tag: string): boolean
Returns true if the current update has the specified tag.
Selection Utilities
$insertNodes
function $insertNodes(nodes: Array<LexicalNode>): void
Inserts nodes at the current selection.
$isBlockElementNode
function $isBlockElementNode(node: LexicalNode | null | undefined): boolean
Returns true if the node is a block-level element.
DOM Utilities
getDOMSelection
function getDOMSelection(targetWindow?: Window | null): Selection | null
Returns the DOM Selection object.
The window to get selection from
isHTMLElement
function isHTMLElement(x: Node | EventTarget | null): x is HTMLElement
Type guard for HTMLElement.
isDOMNode
function isDOMNode(x: unknown): x is Node
Type guard for DOM Node.
isDOMTextNode
function isDOMTextNode(x: unknown): x is Text
Type guard for DOM Text node.
Text Direction
getTextDirection
function getTextDirection(text: string): 'ltr' | 'rtl' | null
Detects text direction from content.
Class Name Utilities
addClassNamesToElement
function addClassNamesToElement(element: HTMLElement, ...classNames: Array<string>): void
Adds class names to a DOM element.
removeClassNamesFromElement
function removeClassNamesFromElement(element: HTMLElement, ...classNames: Array<string>): void
Removes class names from a DOM element.
normalizeClassNames
function normalizeClassNames(...classNames: Array<typeof undefined | boolean | null | string>): Array<string>
Normalizes class names, filtering out falsy values.
Listener Utilities
mergeRegister
function mergeRegister(...func: Array<() => void>): () => void
Combines multiple unregister functions into one.
func
Array<() => void>
required
Array of cleanup functions
A single cleanup function
import { mergeRegister } from 'lexical';
const removeListeners = mergeRegister(
editor.registerUpdateListener(updateListener),
editor.registerCommand(COMMAND, handler, PRIORITY)
);
// Later, cleanup both at once
removeListeners();
Example: Common Patterns
Get All Text Nodes
import { $nodesOfType, TextNode } from 'lexical';
editor.update(() => {
const textNodes = $nodesOfType(TextNode);
textNodes.forEach(node => {
console.log(node.getTextContent());
});
});
Find Parent of Type
import { $findMatchingParent, $isParagraphNode } from 'lexical';
editor.update(() => {
const selection = $getSelection();
if ($isRangeSelection(selection)) {
const node = selection.anchor.getNode();
const paragraph = $findMatchingParent(node, $isParagraphNode);
}
});
Clone and Insert Node
import { $copyNode, $getNodeByKey } from 'lexical';
editor.update(() => {
const node = $getNodeByKey('some-key');
if (node) {
const copy = $copyNode(node);
const root = $getRoot();
root.append(copy);
}
});