CKEditor 4 React Integration - Deprecated
There is a newer version of React Integration available! This version is not maintained anymore. We strongly encourage everyone to migrate to latest version.
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 a 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 v16. However, we strongly advise to use latest version.
# 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@1
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.