Basic & Dynamic Usage
Learn how to use <Editor /> in your React application as a controlled component with value and onChange, with custom toolbar presets, menubar options, disabled/read-only modes, and programmatic methods.
Controlled value + onChange
Omitting the init prop activates the default full-featured editor configuration.
import { useState } from 'react';
import { Editor } from '@erag/text-editor-react';
import '@erag/text-editor-react/style.css';
export default function App() {
const [content, setContent] = useState(
'<p>Welcome to <strong>@erag/text-editor-react</strong>!</p>',
);
return (
<div className="editor-wrapper">
<Editor value={content} onChange={setContent} />
</div>
);
}onChange receives the new HTML string, so you can pass any handler and combine it with other props and callbacks:
<Editor
value={content}
disabled={isDisabled}
onChange={(html) => setContent(html)}
onClick={handleClick}
/>For uncontrolled usage, pass defaultValue instead of value and read the HTML later through a ref, onCommit, or the name hidden input:
<Editor defaultValue="<p>Initial content</p>" name="body" />Toolbar Presets
Minimal Toolbar
For comment sections, chat boxes, or simple input forms, you can configure a minimal toolbar and hide the menubar and statusbar:
import { useState } from 'react';
import { Editor, type EditorInit } from '@erag/text-editor-react';
const minimalConfig: EditorInit = {
height: 220,
menubar: false,
statusbar: false,
toolbar: 'bold italic underline | bullist numlist | link removeformat',
};
export default function CommentBox() {
const [content, setContent] = useState('');
return <Editor value={content} onChange={setContent} init={minimalConfig} />;
}Full Custom Toolbar
You can separate groups using | or pass specific control names:
const fullConfig: EditorInit = {
height: 450,
minHeight: 250,
maxHeight: 800,
placeholder: 'Type your story here...',
menubar: true,
toolbar:
'undo redo | blocks fontfamily fontsize lineheight | bold italic underline strikethrough superscript subscript casechange | ' +
'forecolor backcolor | alignment | ' +
'bullist numlist checklist outdent indent | link image media table | hr removeformat | ' +
'code preview fullscreen',
statusbar: true,
resize: true,
};Menubar Configuration
Customized menubar entries can be array-defined or hidden entirely:
{/* Explicit menubar options */}
<Editor
value={content}
onChange={setContent}
init={{ menubar: ['file', 'edit', 'insert', 'format'] }}
/>
{/* Hide menubar completely */}
<Editor value={content} onChange={setContent} init={{ menubar: false }} />Disabled & Read-only Modes
@erag/text-editor-react supports both disabled and readOnly modes:
disabled: Disables all interactions, toolbar buttons, and user editing canvas.readOnly: Allows viewing, text selection, source code inspection, and preview while preventing content mutation.
In read-only mode these actions keep working: Fullscreen, Print, Word count, Copy, Select all (selects only the editor content), Preview, Source code (view only), Shortcuts, and About. All other toolbar buttons and menu items are shown as disabled. The toolbar More button stays usable so hidden read-only actions can still be reached.
<>
{/* Disabled mode */}
<Editor value={content} onChange={setContent} disabled />
{/* Read-only mode */}
<Editor value={content} onChange={setContent} readOnly />
</>Dynamic Configuration
The editor detects init changes structurally, so you can derive the configuration from component state with an inline object or useMemo:
import { useMemo, useState } from 'react';
import { Editor, type EditorInit } from '@erag/text-editor-react';
export default function DynamicEditor() {
const [isCompact, setIsCompact] = useState(false);
const [content, setContent] = useState('');
const dynamicInit = useMemo<EditorInit>(
() => ({
height: isCompact ? 260 : 500,
menubar: !isCompact,
toolbar: isCompact ? 'bold italic link' : true,
}),
[isCompact],
);
return (
<>
<button type="button" onClick={() => setIsCompact((value) => !value)}>
Toggle Mode
</button>
<Editor value={content} onChange={setContent} init={dynamicInit} />
</>
);
}Programmatic Control (EditorInstance)
Access the editor instance methods via a React ref:
import { useRef, useState } from 'react';
import { Editor, type EditorInstance } from '@erag/text-editor-react';
export default function SignatureEditor() {
const editorRef = useRef<EditorInstance>(null);
const [content, setContent] = useState('');
function insertSignature() {
editorRef.current?.focus();
editorRef.current?.insertHtml(
'<p>Best regards,<br><strong>Er Amit Gupta</strong></p>',
);
}
function clearEditor() {
editorRef.current?.clear();
}
function printHtml() {
console.log(editorRef.current?.getHtml());
}
return (
<>
<div className="actions">
<button type="button" onClick={insertSignature}>
Insert Signature
</button>
<button type="button" onClick={clearEditor}>
Clear
</button>
<button type="button" onClick={printHtml}>
Log HTML
</button>
</div>
<Editor ref={editorRef} value={content} onChange={setContent} />
</>
);
}Available Instance Methods
| Method | Parameters | Description |
|---|---|---|
focus() | none | Focuses the editable canvas. |
blur() | none | Blurs focus from the editor. |
getHtml() | none | Returns sanitized HTML string. |
setHtml(html: string) | html | Sets editor HTML content. |
getText() | none | Returns plain text content without HTML tags. |
clear() | none | Replaces the content with an empty string. |
insertHtml(html: string) | html | Inserts HTML fragment at current selection cursor. |
insertText(text: string) | text | Inserts raw text fragment. |
selectAll() | none | Selects all text inside editor. |
undo() | none | Triggers programmatic undo step. |
redo() | none | Triggers programmatic redo step. |
openSourceCode() | none | Opens the HTML source code modal dialog. |
openPreview() | none | Opens the sanitized preview modal dialog. |
getRootElement() | none | Returns the editable content root inside .erag-editor. |