DraftJS Documentation
Draft.js is a framework for building rich text editors in React, powered by an immutable model and abstracting over cross-browser differences.
The Editor
React component is built as a controlled ContentEditable component.
As a brief refresher, controlled inputs involve two key pieces:
- A value to represent the state of the input
- An onChange prop function to receive updates to the input
Draft Editor example
import {Editor, EditorState} from 'draft-js';
class MyEditor extends React.Component {
constructor(props) {
super(props);
this.state = {editorState: EditorState.createEmpty()};
this.onChange = (editorState) => this.setState({editorState});
}
render() {
return <Editor editorState={this.state.editorState} onChange={this.onChange} />;
}
}
The Editor
component has a full set of props that can be used to modify its behaviour.
State is represented as a single immutable EditorState
object, and onChange
is implemented within the Editor
core to provide this state value to the top level.
EditorState
is the top-level state object for the editor, including contents, cursor, and undo/redo history. All changes to content and selection within the editor will create newEditorState
objects. Note that this remains efficient due to data persistence across immutable objects..It includes:
- The current text content state
- The current selection state
- The fully decorated representation of the contents
- Undo/redo stacks
- The most recent type of change made to the contents
For any edits or selection changes that occur in the editor DOM, your onChange
handler will execute with the latest EditorState
object based on those changes.
Since your top-level React component is responsible for maintaining the state, you also have the freedom to apply changes to that EditorState
object in any way you see fit.
For inline and block style behavior, for example, the RichUtils module provides a number of useful functions to help manipulate state. Similarly, the Modifier module also provides a number of common operations that allow you to apply edits, including changes to text, styles, and more.
RichUtils example
import React, { Component, PropTypes } from 'react';
import Editor from 'draft-js-plugins-editor';
import { EditorState, ContentState, RichUtils } from 'draft-js';
class MyEditor extends React.Component {
// …
_onBoldClick = () => {
this.onChange(RichUtils.toggleInlineStyle(this.state.editorState, 'BOLD'));
}
render() {
return (
<div>
<button onClick={this._onBoldClick}>Bold</button>
<Editor
editorState={this.state.editorState}
handleKeyCommand={this.handleKeyCommand}
onChange={this.onChange}
/>
</div>
);
}
}
ContentState
is an Immutable Record that represents the full state of:
- The entire contents of an editor: text, block and inline styles, and entity ranges.
- Two selection states of an editor: before and after the rendering of these contents.
The most common use for the ContentState
object is via EditorState.getCurrentContent()
, which provides the ContentState
currently being rendered in the editor.
ContentBlock
is an Immutable Record that represents the full state of a single block of editor content, including:
- Plain text contents of the block
- Type, e.g. paragraph, header, list item
- Entity, inline style, and depth information
- A ContentState object contains an OrderedMap of these ContentBlock objects, which together comprise the full contents of the editor.
ContentBlock
objects are largely analogous to block-level HTML elements like paragraphs and list items.
New ContentBlock
objects may be created directly using the constructor. Expected Record values are detailed below.
Representing styles and entities
The characterList
field is an immutable List
containing a CharacterMetadata
object for every character in the block. This is how we encode styles and entities for a given block.
By making heavy use of immutability and data persistence for these lists and CharacterMetadata
objects, edits to the content generally have little impact on the memory footprint of the editor.
By encoding inline styles and entities together in this way, a function that performs edits on a ContentBlock
can perform slices, concats, and other List methods on a single List
object.