New Froala Editor v5.3.0 is here – Learn More
Froala Documentation
- Installation Guides
- Browser Support
- Languages Support
- Shortcuts
- Activation
- Examples
- Customize the Editor
- Use-cases
- Plugins
- APIs
- Development Frameworks
- Server Integrations
- Server SDKs
- Migration Guides
- Changelog
- Tutorials
- Froala Docs
- /
- Migration Guides
- /
- Migrate from Summernote to Froala
Migrate from Summernote to Froala
This guide maps the latest Summernote (jQuery) API onto the Froala WYSIWYG Editor, giving you side-by-side code for every common task — initialization, configuration, plugins, content, events, methods, image upload, and React — so you can switch with confidence.
What you need to know first
Summernote is a jQuery plugin. Every interaction flows through a single overloaded $(selector).summernote(...) call: pass an options object to initialize, or pass a command string such as 'code' or 'destroy' to invoke a method. It depends on jQuery, and traditionally on Bootstrap, to render its UI. Froala is a standalone ES6 library with no jQuery or Bootstrap dependency. You create an instance with new FroalaEditor(selector, options) and call structured, namespaced methods on it directly — for example editor.html.get() instead of $(el).summernote('code').
Both editors are HTML-first: they read and write HTML strings, so your stored content carries over without a data-model conversion. The other practical difference is licensing. Summernote is MIT-licensed and free. Froala is a commercial product that requires a license key passed in the options; you can evaluate it without a key (a small notice appears in the editor).
| Concept | Summernote | Froala |
|---|---|---|
| Initialization | $('#editor').summernote(options) | new FroalaEditor('#editor', options) |
| Element targeting | jQuery selector on a div or textarea | CSS selector or DOM node — div, textarea, span, even an img |
| Enabling features | Pre-bundled in BS3/BS4/BS5/Lite builds | 30+ pluginsEnabled plugins |
| Toolbar | toolbar array of [group, [buttons]] | toolbarButtons array of button groups |
| Reading content | $('#editor').summernote('code') | editor.html.get() |
| Writing content | $('#editor').summernote('code', html) | editor.html.set(html) |
| Events | callbacks: { onChange: … } | events: { contentChanged: … } |
| Teardown | $('#editor').summernote('destroy') | editor.destroy() |
| Licensing | Free, MIT license | Commercial license key (key option) |
The one mental shift: stop routing everything through one$(el).summernote('command', args)string and start holding theFroalaEditorinstance you create, then call its namespaced methods directly —editor.html.get(),editor.events.on(...),editor.edit.off(). The instance is your API.
Swap Summernote for Froala in three steps
Remove the Summernote stack, drop in Froala's single CSS/JS pair, then initialize. Because both editors read the container's existing HTML as their starting content, you usually keep the same markup.
Step 1 — Remove Summernote
Delete the Summernote assets and — if nothing else on the page needs them — the jQuery and Bootstrap dependencies it relied on. Froala needs none of them.
<!-- jQuery + Bootstrap (only needed by Summernote) -->
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet">
<!-- Summernote assets -->
<link href="https://cdn.jsdelivr.net/npm/summernote@0.9.0/dist/summernote-bs4.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/summernote@0.9.0/dist/summernote-bs4.min.js"></script>
Step 2 — Add Froala
Add the single packaged stylesheet and script. The .pkgd build bundles every plugin so you can enable features purely through options. Or install from npm.
// Three libraries: jQuery, Bootstrap, Summernote
// (plus a build variant per Bootstrap version)
<!-- CDN: one CSS + one JS, no dependencies -->
<link href="https://cdn.jsdelivr.net/npm/froala-editor@latest/css/froala_editor.pkgd.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/froala-editor@latest/js/froala_editor.pkgd.min.js"></script>
npm install froala-editor
Step 3 — Initialize the editor
Summernote initializes through the jQuery plugin and runs inside $(document).ready. Froala is a constructor — keep the returned instance, because that object is how you call every method later. Both editors accept a div or a textarea, and both treat the element's existing HTML as the initial content. Add your commercial key in the options.
$(document).ready(function () {
$('#editor').summernote();
});
const editor = new FroalaEditor('#editor', {
key: 'YOUR_FROALA_LICENSE_KEY'
});
Nodocument.readyneeded: Froala attaches as soon as the constructor runs, as long as the target element already exists in the DOM. Place the script after the element, or wrap it in aDOMContentLoadedlistener.
Configuration and options
Both editors take a plain options object. Most Summernote options have a direct Froala counterpart; the names differ but the intent maps cleanly. The toolbar is the biggest structural change: Summernote groups buttons as nested [groupName, [buttons]] arrays, while Froala uses a flat toolbarButtons array and inserts separators with '|'.
Common options, side by side
$('#editor').summernote({
placeholder: 'Write here...',
height: 300,
focus: true,
tabsize: 2,
lang: 'en-US',
spellCheck: true,
toolbar: [
['style', ['bold', 'italic', 'underline', 'clear']],
['para', ['ul', 'ol', 'paragraph']],
['insert', ['link', 'picture']]
]
});
new FroalaEditor('#editor', {
key: 'YOUR_FROALA_LICENSE_KEY',
placeholderText: 'Write here...',
heightMin: 300,
autofocus: true,
tabSpaces: 2,
language: 'en_us',
spellcheck: true,
toolbarButtons: [
'bold', 'italic', 'underline', 'clearFormatting', '|',
'formatUL', 'formatOL', 'paragraphFormat', '|',
'insertLink', 'insertImage'
]
});
Option name reference
| Purpose | Summernote | Froala |
|---|---|---|
| Placeholder | placeholder | placeholderText |
| Fixed height | height | heightMin / heightMax |
| Autofocus | focus | autofocus |
| Tab size | tabsize | tabSpaces |
| Language | lang: 'en-US' | language: 'en_us' |
| Spellcheck | spellCheck | spellcheck |
| Toolbar | toolbar (nested groups) | toolbarButtons (flat, '|' separators) |
| Disable drag & drop | disableDragAndDrop | dragInline / image drag options |
| Paragraph styles | styleTags | paragraphFormat |
| Font names | fontNames | fontFamily |
Browse the full list in the Froala options reference.
Plugins
Summernote ships its features baked into each build (BS3, BS4, BS5, Lite) and you opt in by adding the relevant buttons to the toolbar. Froala makes features explicit through the pluginsEnabled option. The packaged .pkgd build includes every plugin; listing them in pluginsEnabled controls which actually load, which keeps the editor lean.
// Features are bundled; you surface them
// by adding buttons to the toolbar.
$('#editor').summernote({
toolbar: [
['insert', ['link', 'picture', 'video', 'table']]
]
});
new FroalaEditor('#editor', {
key: 'YOUR_FROALA_LICENSE_KEY',
pluginsEnabled: ['link', 'image', 'video', 'table', 'lists']
});
If you prefer to start from "everything on" and switch a few features off, use the inverse option, pluginsDisabled. Anything listed there is excluded while every other bundled plugin stays active.
new FroalaEditor('#editor', {
key: 'YOUR_FROALA_LICENSE_KEY',
// All bundled plugins load except these:
pluginsDisabled: ['video', 'table']
});
Tip: usepluginsEnabledfor an allow-list (smaller, predictable toolbar) andpluginsDisabledfor a deny-list (start full-featured, trim a few). See the full catalog in the plugins reference.
Getting and setting content
Summernote overloads its 'code' command: call it with no argument to read HTML, or with a string to write it. Froala splits these into two clearly named methods on the instance, html.get() and html.set(). Both editors work in HTML, so the value you read from Summernote can be passed straight into Froala.
Reading the HTML
var markup = $('#editor').summernote('code');
const markup = editor.html.get();
Writing the HTML
$('#editor').summernote('code', '<p>Hello world</p>');
// Replace all content
editor.html.set('<p>Hello world</p>');
// Or insert at the cursor
editor.html.insert('<strong>inline</strong>');
To insert plain text at the cursor — Summernote's insertText command — use Froala's html.insert() with the text, or the typing API for finer control.
Events
Summernote registers handlers under a callbacks object (or via jQuery's summernote.* custom events). Froala uses an events object with the same shape, and inside every handler this is the editor instance — so you can read or mutate content right from the callback. You can also bind later with editor.events.on(name, handler).
Registering at initialization
$('#editor').summernote({
callbacks: {
onInit: function () {
console.log('Editor ready');
},
onChange: function (contents) {
console.log('Changed:', contents);
},
onFocus: function () {},
onBlur: function () {}
}
});
new FroalaEditor('#editor', {
key: 'YOUR_FROALA_LICENSE_KEY',
events: {
'initialized': function () {
console.log('Editor ready');
},
'contentChanged': function () {
// this is the editor instance
console.log('Changed:', this.html.get());
},
'focus': function () {},
'blur': function () {}
}
});
Event name reference
| When | Summernote | Froala |
|---|---|---|
| Editor ready | onInit | initialized |
| Content changed | onChange | contentChanged |
| Gained focus | onFocus | focus |
| Lost focus | onBlur | blur |
| Key released | onKeyup | keyup |
| Key pressed | onKeydown | keydown |
| Paste | onPaste | paste.after / paste.before |
| Image uploaded | onImageUpload | image.uploaded / image.inserted |
The full list lives in the Froala events reference.
Methods
In Summernote, you invoke a method by passing its name as a string to the plugin: $('#editor').summernote('disable'). In Froala, you call a namespaced method on the instance you saved at init: editor.edit.off(). Holding that instance reference is the key habit to build.
Frequently used methods
| Action | Summernote | Froala |
|---|---|---|
| Disable editing | summernote('disable') | editor.edit.off() |
| Enable editing | summernote('enable') | editor.edit.on() |
| Focus | summernote('focus') | editor.events.focus() |
| Empty check | summernote('isEmpty') | editor.core.isEmpty() |
| Undo | summernote('undo') | editor.undo() |
| Redo | summernote('redo') | editor.redo() |
| Clear content | summernote('reset') | editor.html.set('') |
| Toggle code view | summernote('codeview.toggle') | editor.codeView.toggle() |
| Destroy | summernote('destroy') | editor.destroy() |
Enable, disable and tear down
$('#editor').summernote('disable');
$('#editor').summernote('enable');
$('#editor').summernote('destroy');
editor.edit.off();
editor.edit.on();
editor.destroy();
See every method in the Froala methods reference.
Image upload
Summernote does not upload by default — it base64-encodes images into the HTML unless you override the onImageUpload callback and post the file to your server yourself. Froala makes server upload a first-class feature: point imageUploadURL at your endpoint and the editor handles the multipart request, progress, insertion, and error events for you.
$('#editor').summernote({
callbacks: {
onImageUpload: function (files) {
var data = new FormData();
data.append('file', files[0]);
$.ajax({
url: '/upload',
method: 'POST',
data: data,
processData: false,
contentType: false,
success: function (url) {
$('#editor').summernote('insertImage', url);
}
});
}
}
});
new FroalaEditor('#editor', {
key: 'YOUR_FROALA_LICENSE_KEY',
// Editor builds the request and inserts the result
imageUploadURL: '/upload',
imageUploadMethod: 'POST',
imageUploadParam: 'file',
events: {
'image.uploaded': function (response) {
// response is the raw server response
console.log('Uploaded:', response);
},
'image.error': function (error, response) {
console.error(error.message);
}
}
});
Server response: Froala expects your endpoint to return JSON containing the uploaded file's link, for example { "link": "/uploads/photo.jpg" }. Froala provides ready-made server SDKs for PHP, Node.js, Java, .NET, Python, and Ruby — see Uploading images. Framework integration — React
Summernote has no official React package; teams usually rely on the community react-summernote wrapper or hand-roll a jQuery bridge inside useEffect. Froala ships an official, maintained component, react-froala-wysiwyg, with controlled-value support through model and onModelChange.
npm install react-froala-wysiwyg froala-editor
import ReactSummernote from 'react-summernote';
import 'react-summernote/dist/react-summernote.css';
import 'jquery';
import 'bootstrap/js/dist/modal';
function Editor() {
return (
<ReactSummernote
value="<p>Hello</p>"
onChange=handleChange
/>
);
}
import { useState } from 'react';
import FroalaEditorComponent from 'react-froala-wysiwyg';
import 'froala-editor/css/froala_editor.pkgd.min.css';
import 'froala-editor/js/plugins.pkgd.min.js';
function Editor() {
const [model, setModel] = useState('<p>Hello</p>');
return (
<FroalaEditorComponent
tag='textarea'
model=model
onModelChange=setModel
config={{ key: 'YOUR_FROALA_LICENSE_KEY' }}
/>
);
}
Controlled by default: bindmodelto state and update it inonModelChange. Froala also publishes first-party components for Angular and Vue.
Feature mapping reference
A consolidated cheat sheet for the most common migration tasks. Keep your stored HTML as-is, swap the calls, and add your license key.
| Task | Summernote | Froala |
|---|---|---|
| Initialize | $('#e').summernote(opts) | new FroalaEditor('#e', opts) |
| Get HTML | summernote('code') | editor.html.get() |
| Set HTML | summernote('code', html) | editor.html.set(html) |
| Insert HTML | summernote('pasteHTML', html) | editor.html.insert(html) |
| Insert text | summernote('insertText', txt) | editor.html.insert(txt) |
| Insert image | summernote('insertImage', url) | editor.image.insert(url) |
| Create link | summernote('createLink', {…}) | editor.link.insert(url, text) |
| Bold | summernote('bold') | editor.format.toggle('bold') |
| Foreground color | summernote('foreColor', c) | editor.colors.text(c) |
| Focus | summernote('focus') | editor.events.focus() |
| Disable / enable | summernote('disable' | 'enable') | editor.edit.off() / editor.edit.on() |
| Is empty | summernote('isEmpty') | editor.core.isEmpty() |
| Code view | summernote('codeview.toggle') | editor.codeView.toggle() |
| Undo / redo | summernote('undo' | 'redo') | editor.undo() / editor.redo() |
| Destroy | summernote('destroy') | editor.destroy() |
| Content event | callbacks.onChange | events.contentChanged |
| Image upload | callbacks.onImageUpload | imageUploadURL option |
You're ready to ship
You’ve swapped the library, mapped your options, rewired events and methods, and moved image upload to a real endpoint. From here, lean on Froala’s references to fine-tune the toolbar, plugins, and framework setup.
Do you think we can improve this article? Let us know.
Whats on this page hide