Toast UI Editor는 이미지 업로드 시 이미지가 base64의 형태로 자동 변환되어 업로드된다.
base64는 엄청 긴 문자열이기 때문에 이를 데이터 베이스에 업로드시 여러분의 데이터 베이스는 살아남지 못할 것
그래서 이미지 업로드시 콜백 함수로 서버의 어떤 위치에 저장을 한 후에 해당 사진의 url을 리턴 값으로 받아서 에디터에 출력시켜주어야 한다.
TUI Editor가 요즘 뜨는 신흥강자라고 해서 나도 이번 프로젝트에 적용하며 사용해보다가
저 부분을 개선하기 위해 인터넷을 서칭해보고
addImageBlobHook을 이용하면 된다는 걸 보고 적용하려 했는데
base64랑 url이 두 개 다 삽입이 되는 것이다...ㅠㅠㅠㅠ
개선하기 위해 해당 깃 헙의 이슈를 뒤졌는데 해결한 분이 있긴 했다.
https://github.com/nhn/tui.editor/issues/1588
removeHook을 이용해서 디폴트 함수를 제거한 후에 다시 세팅을 해야 하는데 아무리 뒤져봐도 잘 안 보이고 감이 안 오는 것...
근데 그냥 공식문서에 있었다 ㅠㅠㅠ
리액트 카톡방에 올려서 선배님께 답변을 받아 잘 적용했다... 바보 같은 나 ㅠㅠㅠ
감사합니다...
적용 코드!
editorRef가 컴포넌트에 떠야 해당 인스턴스를 제어할 수 있으니 useEffect를 이용
import React, { useRef, useEffect } from "react";
import "@toast-ui/editor/dist/toastui-editor.css";
import { Editor } from "@toast-ui/react-editor";
import axios from "axios";
import { backUrl } from "../../config/config";
const TextEditor = ({ setText }) => {
const editorRef = useRef();
useEffect(() => {
if (editorRef.current) {
editorRef.current.getInstance().removeHook("addImageBlobHook");
editorRef.current
.getInstance()
.addHook("addImageBlobHook", (blob, callback) => {
(async () => {
let formData = new FormData();
formData.append("file", blob);
axios.defaults.withCredentials = true;
const { data: url } = await axios.post(
`${backUrl}image.do`,
formData,
{
header: { "content-type": "multipart/formdata" },
}
);
callback(url, "alt text");
})();
return false;
});
}
return () => {};
}, [editorRef]);
return (
<div>
<Editor
usageStatistics={false}
initialValue="스터디에 대한 정보를 간략히 작성해주세요 '-'"
previewStyle="tab"
height="600px"
initialEditType="wysiwyg"
useCommandShortcut={true}
onChange={() => {
const innerTxt = editorRef.current.getInstance().getMarkdown();
setText(innerTxt);
}}
ref={editorRef}
/>
</div>
);
};
export default TextEditor;
---------- 내용 추가
🥸 Vue용 TUI Editor
지금 버전의 에디터 소스코드가 어떻게 달라졌는 지는 모르겠지만, 최근 글을 찾아보니 addHook 호출 시 기존에 있는 이벤트를 제거하고 해당 함수를 덮어준다고 합니다.
일단 Editor에 ref로 해당 객체를 가지고 올 수 있게 하는 점은 동일한데, 인스턴스를 어떻게 가지고 오는 지와, addHook만 호출해도 됐던 점이 리액트 버전과 다른 점 인 것 같아요.
외부 비동기 호출하는 것은 위와 유사하게 하시면 될 것 같아요.
imageURL은 dogg 이라고 쳤는데 스눕독 나오길래 그대로 갖다 썼는데;;(놀라지마세요..),
axios로 업로드하고 해당 URL받아서 처리하는 부분은 동일하니 그렇게 하시면 될 것 같습니다.
<template>
<div>
<editor
ref="toastEditor"
:options="editorOptions"
/>
</div>
</template>
<script>
import '@toast-ui/editor/dist/toastui-editor.css';
import { Editor } from '@toast-ui/vue-editor';
export default {
components: {
editor: Editor
},
data() {
return {
editorOptions: {
usageStatistics: false,
},
};
},
mounted() {
console.log(this.$refs.toastEditor)
const instance = this.$refs.toastEditor
const imageURL= "https://www.biography.com/.image/ar_16:9%2Cc_fill%2Ccs_srgb%2Cfl_progressive%2Cq_auto:good%2Cw_1200/MTQ3NjM5ODIyNjU0MTIxMDM0/snoop_dogg_photo_by_estevan_oriol_archive_photos_getty_455616412.jpg"
instance.invoke("addHook", "addImageBlobHook", function(
file,
callback
) {
const el = instance.$el;
console.log(el)
console.log(file)
callback(imageURL)
});
}
};
</script>
Thymeleaf 템플릿용 추가 (npm이 아닌 cdn 방식에서 활용하기)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" type="text/css" href="https://uicdn.toast.com/editor/latest/toastui-editor.min.css" />
</head>
<body>
<div id="editor"></div>
<script th:src="@{https://uicdn.toast.com/editor/latest/toastui-editor-all.min.js}"></script>
<script>
const Editor = toastui.Editor;
const editor = new Editor({
el: document.querySelector('#editor'),
height: '600px',
initialEditType: 'markdown',
previewStyle: 'vertical',
});
editor.addHook("addImageBlobHook", function(blob, callback){
// blob 텍스트
console.log(blob)
// !!!!! 여기서 이미지를 받아와서 이미지 주소를 받아오고 (ajax 등으로)
// callback의 인수로 넣으시면 됩니다.
callback("콜백으로 받아온 이미지 URL")
})
// 텍스트 가지고 오기
console.log(editor.getMarkdown())
</script>
</body>
</html>
올리는 건 별로 없지만...
블로그 관리는 계속 할 예정입니다 ㅠ_ㅜ
이 글로 유입되는 분들이 많으신데 댓글 많이 달아주세요...ㅎㅎ
궁금한 점이 있으시다면 제가 할 수 있는 선에서 최대한 도움 드리겠습니다 :0
위의 소스를 깃허브에 올려두었어요
혹시 길 잃으시거나 잘 모르시겠는 분들은 위의 포스팅(깃허브) 참고해주세요
'Front-end > React.js' 카테고리의 다른 글
[React] Ag-grid 를 이용한 floating header 제작하기 (0) | 2020.01.21 |
---|---|
React 에서 SetInterval 로 state 변화주기 (0) | 2020.01.21 |
React material UI를 이용해 커스텀 툴팁 만들기 (0) | 2020.01.21 |
React material UI 를 이용해 커스텀 드롭다운 만들기 (0) | 2020.01.21 |