Days
Hours
Minutes
Seconds
x
Skip to content
Froala Documentation

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 the FroalaEditor instance 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'
});
No document.ready needed: 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 a DOMContentLoaded listener.

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: use pluginsEnabled for an allow-list (smaller, predictable toolbar) and pluginsDisabled for 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: bind model to state and update it in onModelChange. 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.

Ready to dive in? Explore our plans