Contribute to this guideReport an issue

guideCKEditor 4 WYSIWYG Editor React Integration

This feature is provided through the ckeditor4-react npm package.

CKEditor 4 offers a native React integration through the CKEditor 4 React component. It provides deep integration of CKEditor 4 and React that lets you use the native features of the WYSIWYG editor inside a React component. The CKEditor 4 React component is compatible with React versions 16.0+.

# Basic Usage

In order to create an editor instance in React, install the ckeditor4-react npm package as a dependency of your project:

npm install ckeditor4-react

After installing, the CKEditor 4 React component can be imported in your JavaScript code:

import CKEditor from 'ckeditor4-react';

An example App component featuring CKEditor would look like the following:

import React, { Component } from 'react';
import CKEditor from 'ckeditor4-react';

class App extends Component {
    render() {
        return (
            <div className="App">
                <h2>Using CKEditor 4 in React</h2>
                <CKEditor
                    data="<p>Hello from CKEditor 4!</p>"
                />
            </div>
        );
    }
}

export default App;

The data property used in the example above is responsible for setting the WYSIWYG editor’s data.

# Customizing CKEditor Preset or Version

By default, the CKEditor 4 React component loads the standard-all preset of the latest CKEditor 4 release from the CDN when creating the first editor. This behavior can be altered by changing the value of the CKEditor.editorUrl variable to point to the desired CKEditor script location:

CKEditor.editorUrl = 'https://your-website.example/ckeditor/ckeditor.js';

Note that the variable must be assigned before the first component is initialized.

Alternatively, you can load CKEditor before loading the CKEditor 4 React component. In this case the component will use the already loaded CKEditor:

<script src="custom-ckeditor.js"></script>
<script src="node_modules/react/react.production.min.js"></script>
<script src="node_modules/react-dom/react-dom.production.min.js"></script>
<script src="node_modules/ckeditor4-react/dist/ckeditor.js"></script>
<script src="app.js"></script>

# Event Handlers

The CKEditor 4 React component allows you to bind any event handler to the editor with properties that start with on. The on is followed by the name of the event with the first letter capitalized, for example, an event handler for the change event would be written as onChange:

<CKEditor
    data="<p>Editor's content</p>"
    onChange={evt => console.log( evt )}
/>

There are also two events not present in CKEditor 4 but available in CKEditor 4 React component by default: onBeforeLoad and onNamespaceLoaded.

# Data Binding

Wrapping the CKEditor 4 React component in another component allows to create a two-way binding between the editor’s data and the content of external elements. This way updating the editor will update the elements and vice versa:

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import CKEditor from 'ckeditor4-react';

class TwoWayBinding extends Component {
    constructor( props ) {
        super( props );

        this.state = {
            data: '<p>React is really <em>nice</em>!</p>'
        };

        this.handleChange = this.handleChange.bind( this );
        this.onEditorChange = this.onEditorChange.bind( this );
    }

    onEditorChange( evt ) {
        this.setState( {
            data: evt.editor.getData()
        } );
    }

    handleChange( changeEvent ) {
        this.setState( {
            data: changeEvent.target.value
        } );
    }

    render() {
        return (
            <div>
                <CKEditor
                    data={this.state.data}
                    onChange={this.onEditorChange} />
                    <label>
                        Change value:
                        <textarea defaultValue={this.state.data} onChange={this.handleChange} />
                    </label>
                    <EditorPreview data={this.state.data} />
            </div>
        );
    }
}

class EditorPreview extends Component {
    render() {
        return (
            <div className="editor-preview">
                <h2>Rendered content</h2>
                <div dangerouslySetInnerHTML={ { __html: this.props.data } }></div>
            </div>
        );
    }
}

EditorPreview.defaultProps = {
    data: ''
};

EditorPreview.propTypes = {
    data: PropTypes.string
};

export default TwoWayBinding;

# Editor Instance

In most cases there is no need to break the encapsulation provided by the CKEditor 4 React component as the editor configuration and event handlers can be configured with the component’s properties. However, if you need access to the editor object, you can use the editor property of the component’s instance:

component.editor.getData();

Please note that this property is initialised asynchronously, after mounting the component.

# Component Properties

# config

Object

Custom configuration can be passed to the editor with the config property of the CKEditor 4 React component. The following example shows how to change the contents of the toolbar:

<CKEditor
    data="<p>Editor's content</p>"
    config={ {
        toolbar: [ [ 'Bold' ] ]
    } }
/>

All configuration options can be changed this way.

Defaults to {}.

# data

String

Data to be used to initially fill editor content. It’s passed to setData method with no additional arguments.

For example usage, refer to Basic Usage section above.

Defaults to ''.

# name

String

Provides value for id and name properties of editor’s HTML element.

<CKEditor
    name="myeditor"
/>

Then it is possible to refer to editor instance like this:

const editor = CKEDITOR.instances.myeditor;

The editor element is also accessible via the component itself.

# readOnly

Boolean

Sets the read-only mode:

<CKEditor
    data="<p>Editor's content</p>"
    readOnly={true}
/>

This property takes precedence over the config.readOnly setting.

Defaults to false.

# style

Object

Style rules set that will be applied to editor container with setStyles.

<CKEditor
    data="<p>Editor's content</p>"
    style={{
        'margin-top': '100px',
        'border': '5px solid red'
    }}
/>

Requires component type property to be classic.

# type

'classic' | 'inline'

By default, the CKEditor 4 React component creates classic editor. To create an inline editor, add the type property with the value of inline to the <CKEditor /> tag:

<CKEditor
    data="<p>Some initial data</p>"
    type="inline"
/>

You can also explicitly set the type property to classic to create the classic editor:

<CKEditor
    data="<p>Some initial data</p>"
    type="classic"
/>

Every other value of the type property will be treated as classic.

For more details, look at the Loading CKEditor Script article.

Defaults to 'classic'.

# onBeforeLoad

Function

Callback function with single argument: CKEDITOR namespace. It is invoked each time new editor instance is loaded, but CKEDITOR object always refers to the same namespace.

Note: To modify CKEDITOR namespace it is recommended to use onNamespaceLoaded event.

Simple usage example:

<CKEditor
    data="<p>First editor.</p>"
    onBeforeLoad={ CKEDITOR => {
            console.log( 'First editor loaded!' );
        }
    }
/>

<CKEditor
    data="<p>Second editor.</p>"
    onBeforeLoad={ CKEDITOR => {
            console.log( 'Second editor loaded!' );
        }
    }
/>

Example which shows incorrect usage - it attempts to load the same plugin two times adding it to the same namespace:

<CKEditor
    name="editorOne"
    data="<p>Editor's content</p>"
    onBeforeLoad={ CKEDITOR => {
            // Add external `placeholder` plugin which will be available for each
            // editor instance on the page.
            CKEDITOR.plugins.addExternal( 'placeholder', '/path/to/the/placeholder/plugin', 'plugin.js' );
        }
    }
/>

<CKEditor
    name="editorTwo"
    data="<p>Editor's content</p>"
    onBeforeLoad={ CKEDITOR => {
            // Namespace was already loaded, but this callback will be called anyway.
            // Unnecessary adding the same plugin to the namespace.
            CKEDITOR.plugins.addExternal( 'placeholder', '/path/to/the/placeholder/plugin', 'plugin.js' );
        }
    }
/>

Look at onNamespaceLoaded property to compare behaviors.

# onNamespaceLoaded

Function

Callback function with a single argument: CKEDITOR namespace. It is invoked exactly once regardless the number of editor instances. It is called after CKEDITOR namespace is loaded and before any editor instances are initialized.

This property should be used if you need to modify the CKEDITOR object, e.g. add an external plugin:

<CKEditor
    name="editorOne"
    data="<p>Editor's content</p>"
    onNamespaceLoaded={ CKEDITOR => {
            // Add external `placeholder` plugin which will be available for each
            // editor instance on the page.
            CKEDITOR.plugins.addExternal( 'placeholder', '/path/to/the/placeholder/plugin', 'plugin.js' );
        }
    }
/>

<CKEditor
    name="editorTwo"
    data="<p>Editor's content</p>"
    onNamespaceLoaded={ CKEDITOR => {
            // If namespace was already loaded, this callback will be never called!
            // There will be only one attempt to add external plugin.
            CKEDITOR.plugins.addExternal( 'placeholder', '/path/to/the/placeholder/plugin', 'plugin.js' );
        }
    }
/>

Look at onBeforeLoad property to compare behaviors.

# CKEditor 4 React Integration Demo

See the working “CKEditor 4 React Integration” sample that showcases the most important features of the integration, including choosing the editor type, configuration and events, or setting up two-way data binding.