#27 WYSIWYG Editor with Summernote
5-2-2016

Summary

Integrate Summernote WYSIWYG Editor into your application. Learn how to use AJAX callbacks to filestore your images instead of database Base64.
7
rails wysiwyg view ajax javascript 7:40

Summary

Gemfilegem 'summernote-rails'
gem "refile", require: "refile/rails"
gem "refile-mini_magick"

Generate a new model for your images to be stored. Without Refile (or a similar uploader), the images will be converted to BASE64 and stored within the database.

bashrails g model image image_id image_filename image_size:integer image_content_type
application.js//= require summernote
application.css.scss/*
@import "bootstrap-sprockets";
@import "bootstrap";
*/

@import "summernote";
_form.html.erb    
    <%= f.input :summary, as: :summernote %>
    <%= f.input :content, as: :summernote %>


articles.coffee$ ->
  sendFile = (that, file) ->
    data = new FormData
    data.append 'image[image]', file
    $.ajax
      data: data
      type: 'POST'
      url: '/images'
      cache: false
      contentType: false
      processData: false
      success: (data) ->
        img = document.createElement('IMG')
        img.src = data.url
        img.setAttribute('id', data.image_id)
        $(that).summernote 'insertNode', img

  deleteFile = (file_id) ->
    $.ajax
      type: 'DELETE'
      url: "/images/#{file_id}"
      cache: false
      contentType: false
      processData: false

  ready = ->
    $('[data-provider="summernote"]').each ->
      $(this).summernote 
        height: 200
        callbacks: 
          onImageUpload: (files) ->
            img = sendFile(this, files[0])
          onMediaDelete: (target, editor, editable) ->
            image_id = target[0].id
            if !!image_id
              deleteFile image_id
            target.remove()
  $(document).ready(ready)
  $(document).on('page:load', ready)
images_controller.rbclass ImagesController < ApplicationController
  protect_from_forgery except: :create
 
  def create
    @image = Image.new(image_params)
    @image.save
 
    respond_to do |format|
      format.json { render :json => { url: Refile.attachment_url(@image, :image), image_id: @image.image_id } }
    end
  end
 
  def destroy
    @image = Image.find_by(image_id: params[:id])
    @image.destroy
    respond_to do |format|
      format.json { render :json => { status: :ok } }
    end
  end
  
  private
 
  def image_params
    params.require(:image).permit(:image)
  end
end
routes.rbRails.application.routes.draw do
  resources :articles
  resources :images, only: [:create, :destroy]
  root to: 'articles#index'
end
image.rbclass Image < ActiveRecord::Base
  attachment :image
  belongs_to :article
end


zulhfreelancer said almost 2 years ago:

Really awesome video. Thanks!

CarlSosaDev said over 1 year ago:

Thanks very much  for the video!

kobaltz PRO said over 1 year ago:

Thank you for watching

adrianvalenz said about 1 year ago:

Hi there! I just messaged you on Twitter. I actually have a question for Summernote as well. Whenever I save/publish a post that contains an iframe of a youtube video, it redirects me to the show page but it is blank and I have to update it. Have you  tried or noticed that? My customers will want to embed Youtube videos since they are Youtubers and I don't know what to do.

Thank you in advance for your time.

kobaltz PRO said about 1 year ago:

Are you entering the iframe code in the "code view", using the Video button or are you pasting it into the WYSIWYG editor? 

Also, can you share the snippet that you're using to display the content of the editor? For example, do you have a <%= raw @model.content %> or something similar?

nikkos said about 1 year ago:

I have Rails 5 and turbolinks 5. The summernote plugin worked but I had a problem. When I was trying to edit the post, the summernote editor disappear. To fix this I changed one line on coffeescript code:

$(document).on('pages:load', ready)

to

$(document).on('turbolinks:load', ready)

ramonrails said 8 months ago:

Should you also include this in the notes?

class Image < ApplicationRecord # :nodoc:
  attachment :image, type: :image
end


kobaltz PRO said 8 months ago:

Thanks for the heads up. I've updated the show notes.

ramonrails said 8 months ago:

# config/initializers/refile.rb
Refile.store = Refile::Backend::FileSystem.new(Rails.root.join('public', 'uploads', 'refile_store'))

Maybe this config can be included too in the article. It allows to persist the uploaded attachments properly.

Without this config, the uploads just stay in system tmp or cache folders and eventually get purged.


Andrew Selvadurai said 7 months ago:

Thank you for this video, it was awesome! 

I followed the video and also added aws s3 storage for my app. I am able to upload to s3 but when the images from summernote are loaded the image path of the loaded files are from my local drive and is not loading from s3. Do you know where and how I can configure summernote to display the image from s3 instead of from my local file?

kobaltz PRO said 6 months ago:

It could be an issue on the onImageUpload callback in the summernote initialization. Basically, this callback will listen for image uploads and in the example, we're calling a separate javascript function (sendFile). The sendFile function will make an AJAX post to your application at a different endpoint and will handle the uploading to S3. The success callback of this AJAX request should return a hash with the URL of the S3 image. The success callback will create the image element with the URL from the returned hash and that will be what gets inserted.

Simon Kiteley PRO said 2 months ago:

Love Summernote... does anyione know of a css (or general) code editing equivalent?

kobaltz PRO said 2 months ago:

I've recently switched the Drifting Ruby comments over from Summernote to SimpleMDE which gives better familiarity to code editing WYSIWYG.

Using three backticks, followed by a language, you can create the code blocks

def Foo
     puts bar
end

Simon Kiteley PRO said about 2 months ago:

Thanks.

Login to Comment