6
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

summernote on laravel の導入備忘録

Last updated at Posted at 2020-12-15

インストール(npm)

npm install summernoteでnode_modulesに入る
レイアウトがいろいろ用意されている。
通常はrequire('summernote');で行けるが
日本語化とレイアウトをbootstrap4ベースにしたかったけどサンプルなかった。
多分以下で行けるはず。

resources/js/bootstrap.js
require('summernote/dist/summernote-bs4.min');
require('summernote/dist/lang/summernote-ja-JP.min');
resources/js/app.scss
@import 'summernote/dist/summernote-bs4.min';

フロント側(bladeファイルとjavascript)

divタグを用意するだけ。textareaタグでもよい。

edit.blade.php
<div id="summernote"></div>
<textarea id="summernote" class="form-control" name="description"></textarea>
edit.js
$(document).ready(function()
{
  $('#summernote').summernote({
    lang: 'ja-JP',
    height: 300,
  });
})

画像挿入時のサーバ転送

デフォルトはimgタグにbase64エンコードされたデータとして挿入されます。
独自のサーバにアップロードしてそのURLをimgタグに挿入する方法も用意されている。

  $('#summernote').summernote({
......
    callbacks: {
      onImageUpload: (files) => {
        /* ローカルファイルを選んだあと呼ばれるのでサーバーへアップする */
        insertImageFile(files[0]);
      },
      onMediaDelete: (target) => {
      /* 画像を削除するを選んだ時呼ばれるのでサーバーへ削除要求する */
        removeImageFile(target[0].src);
      },  
    },
......

function insertImageFile(file)
{
  let formData = new FormData();
  formData.append('file', file);
  
  fetch('/insert-image-file', formData,...)
  .then((response) => {
    if (response.ok) {
      // サーバ側で応答に画像のurlを付与する
      let imgNode = document.createElement('img');
      imgNode.src = response.url;
      $('#summernote').summernote('insertNode', imgNode);
    }
  });
}

function removeImageFile(src)
{
  /* 削除のアクションを呼ぶ */
  let formData = new FormData();
  formData.append('src', src);
  fetch('/remove-image-file', formdata, ...)
  .then((response) => {
    if (response.ok) {
    }
  }  
}

サーバ側(laravel/php)ではinsert-image-fileとremove-image-fileに対応する
アクションを用意する。

app/Http/Controller/TestController.php

public function insertImageFile(Request $request)
{
  /* ファイル名をuuidに変換 */
  $uuid = (string) Str::uuid();
  $ext = $request->file('file')->extension();
  $file = $uuid . '.' . $ext;
  $imgpath = $request->file('file')->storeAs('attachments', $file, 'public');
  $url = Storage::disk('public')->url($imgpath);
  return response()->json(['result' => 'OK', 'url' => $url]);
}

public function removeImageFile(Request $request)
{
  /* storageまでのパスを取得 */
  $url = Storage::disk('public')->url('');
  /* 画像のパス(URL)からサーバ内のローカルパスに変換 */
  $delete_file = str_replace($url, '', $request->src);
  $resp = Storage::disk('public')->delete($delete_file);
  return response()->json(['result' => 'OK']);
}

フォームのsubmitアクション

HTMLエディタの入力欄に対応するinputタグがないので
submitのクリックイベントを引っ掛けて隠し属性のinputを追加してsumbmitする
buttonタグにname="submit"があるとformのsubmitが効かないので削除する。
追記(2020/12/15)
普通にtextareaタグにid設定すればsummernoteのレイアウトになるっぽいので
以下の処理は必要ない。

  $("#submit_button").click((e) => {
    /* 一旦submitを無効 */
    e.preventDefault();
    let description = $('#summernote').summernote('code');
    let edit_form = document.getElementById('edit_form');
    if (edit_form != null) {
      inputDescription = document.createElement("input");
      inputDescription.type = 'hidden';
      inputDescription.name = 'description';
      inputDescription.value = description;
      edit_form.appendChild(inputDescription);
      edit_form.submit();
    }
  });
6
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?