I started to integrate a WYSIWYG into my blog project by using React Quill and I have no experience with it before and tried to do the most from the help of internet. Actually everything is working fine from loading images(using Image Handler) to saving it to database(PostgreSQL in Rails).I am saving the contents in HTML and not in Delta format but whenever i try to view it by loading it from database, all the formatting, alignment, and indentation are all gone but (header, italic, underline, bold, text-color) are present ,and everything is left aligned
Any help would be appreciated.
I read the Quill documentation and tried to understand how to deal with this but I don't know how to make this work.
I'm using React + Rails
this is my code (I'll show only relevant code):
CreateBlog.jsx
file
import axios from 'axios'
import React, { useState } from "react";
import PageLoader from '../PageLoader'
import CreateForm from './CreateForm'
export default function CreateBlog({history}) {
const [title, setTitle] = useState("")
const [body, setBody] = useState("")
const [loading, setLoading] = useState(false)
const handleChange = (value)=>{
setBody(value)
console.log(value)
}
const handleSubmit = async (event) => {
event.preventDefault()
const variables = {
title: title,
body: body,
}
try{
const response = await axios.post("/blogs",variables)
setLoading(false)
history.push("/blogs")
} catch(error){
console.log(error)
setLoading(false)
}
}
return (
<CreateForm
setTitle={setTitle}
setBody={setBody}
body={body}
loading={loading}
handleSubmit={handleSubmit}
handleChange={handleChange}
/>
)
}
CreateForm.jsx
file
import React,{useMemo,useRef} from 'react'
import Input from '../Input'
import Button from '../Button'
import 'react-quill/dist/quill.snow.css'
import ReactQuill,{Quill} from "react-quill";
import ImageResize from 'quill-image-resize-module-react';
import Editor from "./Editor";
Quill.register('modules/imageResize', ImageResize);
export default function CreateForm(
{
type="create",
setTitle,setBody,loading,handleSubmit,
handleChange,body
}) {
const editorRef = useRef(null);
const modules = useMemo(()=>({
imageResize: {
parchment: Quill.import('parchment'),
modules: ['Resize', 'DisplaySize', 'Toolbar']
},
toolbar:{
container: [
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
['bold', 'italic', 'underline'],
[
{ 'list': 'ordered' },
{ 'list': 'bullet' },
{ 'indent': "-1" },
{ 'indent': "+1" }
],
[{ 'align': [] }],
['link', 'image', 'video'],
['clean'],
[{ 'color': [] }]
],
handlers: {
image: imageHandler,
},
clipboard: {
matchVisual: false,
}
}
}));
const imageHandler = (a) => {
const input = document.createElement("input");
input.setAttribute("type", "file");
input.setAttribute("accept", "image/*");
input.click();
input.onchange = () => {
const file = input.files[0];
// file type is only image.
if (/^image\//.test(file.type)) {
console.log("image file type",file)
saveToServer(file);
} else {
console.warn("You could only upload images.");
}
};
};
function saveToServer(file) {
const fd = new FormData();
fd.append("upload", file);
const xhr = new XMLHttpRequest();
xhr.open("POST", "/blogs", true);
xhr.upload.onprogress = function(event){
const progress =event.loaded / event.total * 100;
}
xhr.onload = () => {
if (xhr.status === 201) {
const data = JSON.parse(xhr.responseText);
const url = data.url
console.log("Image url",url)
setImage(url)
insertToEditor(url);
}
};
xhr.send(fd);
console.log("formdata",fd)
}
function insertToEditor(url) {
editorRef.current.getEditor().insertEmbed(null, "image", url);
}
return (
<form className="max-w-full" onSubmit={handleSubmit}>
<Input
label="Title"
placeholder="Blog Title (Max 50 Characters Allowed)"
onChange={e => setTitle(e.target.value)}
/>
<ReactQuill
theme="snow"
placeholder="Write your story"
modules={modules}
forwardedRef={editorRef}
onChange={handleChange}
value={body}
/>
<Button
type="submit"
buttonText={type === "create" ? "Create Blog" : "Update Blog"}
loading={loading}
/>
</form>
)
}
Everything is working perfectly when i am editing the contents
like the one in this image
While editing
But after saving the post and again viewing it ,
its something like this (but bold, italics, underline) are showing as desired but ordered lists nand unordered lists, alignment, quotes... etc are not showing as desired.
View after saving
For viewing the contents code is
ShowBlog.jsx
import React,{useState,useEffect} from 'react'
import { useParams } from 'react-router-dom'
import blogsApi from '../apis/blogs'
import axios from 'axios'
import parse from 'html-react-parser';
export default function ShowBlog() {
const componentMounted = true
const {id} = useParams()
const [blogDetails, setBlogDetails] = useState([])
const [loading, setLoading] = useState(true)
const [blogCreator, setBlogCreator] = useState('')
const source = axios.CancelToken.source()
const fetchBlogDetails = async()=>{
try{
const response = await axios.get(`/blogs/${id}`, {cancelToken:source.token})
setBlogDetails(response.data.blog)
setBlogCreator(response.data.blog_creator)
setLoading(false)
console.log("Show Blog details",response)
} catch(error){
if(axios.isCancel(error)){
console.log('cancelled')
}else{
throw error
}
console.log(error)
} finally {
setLoading(false)
}
}
useEffect(()=>{
fetchBlogDetails()
return () => {
source.cancel()
}
}, [])
if(loading){
return <PageLoader />
}
return (
<div className="bg-white">
<div className="max-w-6xl mx-auto mt-10">
<div className="relative max-w-4xl mx-auto items-center justify-between">
<div className="flex flex-col ">
<div className="w-full ">
<h2 className="text-gray-800 ">
{blogDetails?.title}
</h2>
<div className="flex ">
<span>by {blogCreator?.username}</span>
</div>
<div>
{parse(blogDetails.body)}
</div>
</div>
</div>
</div>
</div>
</div>
)
}