react-quill missing style after adding custom toolbar button - javascript

I need to add a custom toolbar button inside the react quill HTML editor.
I have followed the tutorial https://github.com/zenoamaro/react-quill#custom-toolbar but was not able to get this to work. The code is as follows.
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import ReactQuill from 'react-quill'; // ES6
import './style.scss';
class DocumentForm extends Component {
constructor(props) {
super(props);
this.state = {
file: null,
documentDetails: {},
text: ''
};
this.handleEditorChange = this.handleEditorChange.bind(this);
this.modules = {
toolbar: [
[{ 'header': [1, 2, false] }],
['bold', 'italic', 'underline','strike', 'blockquote'],
[{'list': 'ordered'}, {'list': 'bullet'}, {'indent': '-1'}, {'indent': '+1'}],
['link', 'image'],
['clean']
],
}
this.formats = [
'header',
'bold', 'italic', 'underline', 'strike', 'blockquote',
'list', 'bullet', 'indent',
'link', 'image'
]
}
handleEditorChange(value) {
this.setDocumentDetails('html_content', value)
}
render() {
let selectedDocument = this.state.documentDetails;
return (
<div>
<div>
<div className="form-group">
<label>File Content</label>
<Editor placeholder={'Write something or insert a star ★'}/>,
</div>
</div>
</div>
);
}
}
export default DocumentForm
/*
* Custom "star" icon for the toolbar using an Octicon
* https://octicons.github.io
*/
const CustomButton = () => <span className="octicon octicon-star" />
/*
* Event handler to be attached using Quill toolbar module
* http://quilljs.com/docs/modules/toolbar/
*/
function insertStar () {
const cursorPosition = this.quill.getSelection().index
this.quill.insertText(cursorPosition, "★")
this.quill.setSelection(cursorPosition + 1)
}
/*
* Custom toolbar component including insertStar button and dropdowns
*/
const CustomToolbar = () => (
<div id="toolbar">
<select className="ql-header" defaultValue={""} onChange={e => e.persist()}>
<option value="1"></option>
<option value="2"></option>
<option selected></option>
</select>
<button className="ql-bold"></button>
<button className="ql-italic"></button>
<select className="ql-color">
<option value="red"></option>
<option value="green"></option>
<option value="blue"></option>
<option value="orange"></option>
<option value="violet"></option>
<option value="#d0d1d2"></option>
<option selected></option>
</select>
<button className="ql-insertStar">
<CustomButton />
</button>
</div>
)
/*
* Editor component with custom toolbar and content containers
*/
class Editor extends React.Component {
constructor (props) {
super(props)
this.state = { editorHtml: '' }
this.handleChange = this.handleChange.bind(this)
}
handleChange (html) {
this.setState({ editorHtml: html });
}
render() {
return (
<div className="text-editor">
<CustomToolbar />
<ReactQuill
onChange={this.handleChange}
placeholder={this.props.placeholder}
modules={Editor.modules}
/>
</div>
)
}
}
/*
* Quill modules to attach to editor
* See http://quilljs.com/docs/modules/ for complete options
*/
Editor.modules = {
toolbar: {
container: "#toolbar",
handlers: {
"insertStar": insertStar,
}
}
}
/*
* Quill editor formats
* See http://quilljs.com/docs/formats/
*/
Editor.formats = [
'header', 'font', 'size',
'bold', 'italic', 'underline', 'strike', 'blockquote',
'list', 'bullet', 'indent',
'link', 'image', 'color',
]
Unlike the tutorial there were 2 toolbars
The custom toolbar was displayed but the buttons were not having styles.
Also the button handler(insertStar) is not working.
A screenshot of the page is as follows.
Any idea on how to fix this

In Reactquill documentation https://www.npmjs.com/package/react-quill#import-the-stylesheet the stylesheet must be imported as:
require('react-quill/dist/quill.snow.css'); // CommonJS
import 'react-quill/dist/quill.snow.css'; // ES6

According to the quill.js guide, you need to import the CSS like following
#import "~quill/dist/quill.core.css"

Try importing, the stylesheet like:
import "react-quill/dist/quill.snow.css"

Related

How to add Tweet HTML Block to react-quilljs

I'm using 'react-quilljs' package, and I want to add Tweet HTML Block to the toolbar, I couldn't find any tutorial how to in their webpage
The Code I'm Using:
import { useQuill } from 'react-quilljs';
import 'quill/dist/quill.snow.css';
export default function NewPost() {
const [content, setContent] = useState("");
//Quill Editor Toolbar
const modules = {
toolbar:{
container: [
[{'header': '1'}, {'header':'2'}, {'font':'[]'}],
[{size:[]}],
['bold', 'italic', 'underline', 'strike', 'blockquote'],
[{'list': 'ordered'}, {'list': 'bullet'}, {'indent':'-1'}, {'indent':'+1'}],
['link', 'image', imageHandler],
['clean'], ['code-block']
],
},
clipboard: {
matchVisual: false,
},
};
const { quill, quillRef } = useQuill();
useEffect(() => {
if (quill){
quill.on('text-change', () => {
console.log(quillRef.current.firstChild.innerHTML);
setContent(quillRef.current.firstChild.innerHTML)
});
}
}, [quill]);
console.log(content, "this is quill editor")
return (
<div className="newPostContentContainer">
<label className="newPostFormLabel">Post Content:</label
<div className="newPostContentTextareaContainer">
<div dir="auto" style={{ height: '300px', width: '100%', boxSizing: 'border-box'}}>
<div ref={quillRef} />
</div>
</div>
</div>
)
}
the problem is that the toolbar I have right now don't have the tweet HTML block or code sample, I have to add them by myself, which I failed to know how, any help would be appreciated.

React CKEditor5 Form submit not getting the data?

I am using CKeditor in react. On Form submit, why entered data is not coming.
Form submit, CKeditor data is still showing empty
How to get the CKEditor data both in text as well as HTML format.
Please find my code:
import React from "react";
import { CKEditor } from '#ckeditor/ckeditor5-react';
import ClassicEditor from '#ckeditor/ckeditor5-build-classic';
export class UseEditor extends React.Component {
constructor(props)
super(props);
this.state = {
DescriptionTextPlain: "",
DescriptionTextHTML: "",
loading: true,
};
this.handleSubmit = this.handleSubmit.bind(this);
}
handleEditorChange(event, editor) {
console.log({ event, editor });
}
handleSubmit(event) {
const DescriptionTextPlain = this.state.DescriptionTextPlain;
const DescriptionTextHTML = this.state.DescriptionTextHTML;
const data = {
DescriptionTextPlain, DescriptionTextHTML
}
fetch(REQUEST_URL, {
method: 'POST'
}
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<div>
<CKEditor name="DescriptionTextPlain" editor={ClassicEditor}
config={{
toolbar: [
'|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', '|',
'outdent', 'indent', '|', 'insertTable', 'undo', 'redo', 'style',
'strikethrough', 'subscript', 'superscript'
] }}
data={this.state.DescriptionTextPlain || ''}
onReady={editor => { this.editor = editor;}}
onChange={this.handleEditorChange}
Width="100%" Height="125px"
value={this.state.DescriptionTextPlain} />
</div> <input type="submit" name="submit" value="Submit" />
</form>
</div>
);
}
}
export default UseEditor;

How can I implement a custom code block button in react-quill toolbar

I am trying to implement a custom code block button to be inserted in react-quill, but I am not sure how to proceed. I know I need to implement a handler for the code block (I named it code-block) and then add a button with a class name as `ql-code-block, but how can I make the editor display specific code block's style using html and css?
import React, { useState } from 'react';
import { useQuill } from 'react-quilljs';
import 'quill/dist/quill.snow.css'; // Add css for snow theme
export default () => {
const theme = 'snow';
const modules = {
toolbar: {
container: '#toolbar',
handlers: {
'code-block': function () {
console.log('Code-block'); <---- How to implement the handler here
},
},
},
clipboard: {
matchVisual: false,
},
};
const placeholder = 'Compose an epic...';
const formats = ['size', 'bold', 'script'];
const { quill, quillRef } = useQuill({
theme,
modules,
formats,
placeholder,
});
const [content, setContent] = useState('');
React.useEffect(() => {
if (quill) {
quill.on('text-change', () => {
setContent(quill.root.innerHTML);
});
}
}, [quill]);
const submitHandler = (e) => {};
return (
<div style={{ width: 500, height: 300 }}>
<div ref={quillRef} />
<div id='toolbar'>
<select className='ql-size'>
<option value='small' />
<option selected />
<option value='large' />
<option value='huge' />
</select>
<button className='ql-bold' />
<button className='ql-code-block' />
<button className='ql-script' value='sub' />
<button className='ql-script' value='super' />
</div>
<div id='editor' />
<form onSubmit={submitHandler}>
<button type='submit'>Submit</button>
</form>
</div>
);
};

ReactQuill (rich text) - Error: React.Children.only expected to receive a single React element child - React

I have a form and I replaced the textarea with ReactQuill based on this tutorial (https://www.youtube.com/watch?v=DjEANvaZFv0&feature=youtu.be) to get Rich Text. However once I did it, I got an error saying 'Error: React.Children.only expected to receive a single React element child' (see screenshot below).
This only came up after I replaced the textarea with ReactQuill but on the error page it shows me the code in the App.js where I've implemented google authentication with firebase and I'm not sure how the two are connected. How do I fix this?
Here's my AddArticle.js where the form is:
import React, { Component } from "react";
import firebase from "../Firebase";
import ReactQuill from "react-quill";
import "react-quill/dist/quill.snow.css";
import renderHTML from 'react-render-html';
class AddArticle extends Component {
constructor() {
super();
this.ref = firebase.firestore().collection("articles");
this.state = {
title: "",
content: "",
};
}
onChange = (e) => {
const state = this.state;
state[e.target.name] = e.target.value;
this.setState(state);
};
onBodyChange(e) {
this.setState({ content: e });
}
onSubmit = (e) => {
e.preventDefault();
const { title, content } = this.state;
this.ref
.add({
title,
content,
})
.then((docRef) => {
this.setState({
title: "",
content: "",
});
this.props.history.push("/");
})
.catch((error) => {
console.error("Error adding document: ", error);
});
};
render() {
const { title, content } = this.state;
return (
<div className="container">
<br></br>
<br></br>
<br></br>
<div className="panel panel-default">
<div className="panel-heading">
<h3 className="panel-title text-center">Create a new article</h3>
</div>
<br></br>
<br></br>
<div className="panel-body">
<form onSubmit={this.onSubmit}>
<div className="form-group input-group-lg">
<label for="title">Title:</label>
<input
type="text"
className="form-control"
name="title"
value={title}
onChange={this.onChange}
placeholder="Title"
/>
</div>
<div className="form-group">
<label for="content">Content:</label>
<ReactQuill
modules={AddArticle.modules}
formats={AddArticle.formats}
name="content"
onChange={this.onBodyChange}
placeholder="Content"
cols="80"
rows="20"
>
{content}
</ReactQuill>
</div>
<button type="submit" className="btn btn-success">
Submit
</button>
</form>
</div>
</div>
</div>
);
}
}
// Quill Config
AddArticle.modules = {
toolbar: [
[{ header: [1, 2, 3, 4, 5, 6, false] }],
[{ size: [] }],
["bold", "italic", "underline", "strike", "blockquote"],
[
{ list: "ordered" },
{ list: "bullet" },
{ indent: "-1" },
{ indent: "+1" },
],
["link", "image", "video"],
["clean"],
["code-block"],
],
clipboard: {
// toggle to add extra line breaks when pasting HTML:
matchVisual: false,
},
};
AddArticle.formats = [
"header",
"font",
"size",
"bold",
"italic",
"underline",
"strike",
"blockquote",
"list",
"bullet",
"indent",
"link",
"image",
"video",
"code-block",
];
export default AddArticle;
And here is my App.js in case it's relevant:
import React, { Component } from "react";
import "./App.css";
import Navbar from "./components/Navbar";
import Main from "./Main";
import firebase from "firebase";
import StyledFirebaseAuth from "react-firebaseui/StyledFirebaseAuth";
class App extends Component {
state={isSignedIn:false}
uiConfig = {
signInFlow: "popup",
signInOptions: [
firebase.auth.GoogleAuthProvider.PROVIDER_ID
],
callbacks: {
signInSuccess: () => false
}
}
componentDidMount = () => {
firebase.auth().onAuthStateChanged(user => {
this.setState({isSignedIn:!!user})
})
}
render() {
return (
<div>
{this.state.isSignedIn ? (
<span>
<Navbar />
<Main />
</span>
) :
(
<StyledFirebaseAuth
uiConfig={this.uiConfig}
firebaseAuth={firebase.auth()}
/>
)}
</div>
);
}
}
export default App;
As described here, I suggest passing content as ReactQuill's value instead of making it a child:
<ReactQuill
value={this.state.content}
// ... other props are OK
/> // Close the tag: no children

Convert functional component in Class Component in office fabric React js?

I want to convert the functional component to class component.The code of modal is given below in office fabric class component.I want to convert in class component.I am new in the React and facing some difficulty while conversion functional to class component.
import * as React from 'react';
import { Dialog, DialogType, DialogFooter } from 'office-ui-fabric-react/lib/Dialog';
import { PrimaryButton, DefaultButton } from 'office-ui-fabric-react/lib/Button';
import { hiddenContentStyle, mergeStyles } from 'office-ui-fabric-react/lib/Styling';
import { Toggle } from 'office-ui-fabric-react/lib/Toggle';
import { ContextualMenu } from 'office-ui-fabric-react/lib/ContextualMenu';
import { useId, useBoolean } from '#uifabric/react-hooks';
const dialogStyles = { main: { maxWidth: 450 } };
const dragOptions = {
moveMenuItemText: 'Move',
closeMenuItemText: 'Close',
menu: ContextualMenu,
};
const screenReaderOnly = mergeStyles(hiddenContentStyle);
const dialogContentProps = {
type: DialogType.normal,
title: 'Missing Subject',
closeButtonAriaLabel: 'Close',
subText: 'Do you want to send this message without a subject?',
};
export const DialogBasicExample: React.FunctionComponent = () => {
const [hideDialog, { toggle: toggleHideDialog }] = useBoolean(true);
const [isDraggable, { toggle: toggleIsDraggable }] = useBoolean(false);
const labelId: string = useId('dialogLabel');
const subTextId: string = useId('subTextLabel');
const modalProps = React.useMemo(
() => ({
titleAriaId: labelId,
subtitleAriaId: subTextId,
isBlocking: false,
styles: dialogStyles,
dragOptions: isDraggable ? dragOptions : undefined,
}),
[isDraggable],
);
return (
<>
<Toggle label="Is draggable" onChange={toggleIsDraggable} checked={isDraggable} />
<DefaultButton secondaryText="Opens the Sample Dialog" onClick={toggleHideDialog} text="Open Dialog" />
<label id={labelId} className={screenReaderOnly}>
My sample label
</label>
<label id={subTextId} className={screenReaderOnly}>
My sample description
</label>
<Dialog
hidden={hideDialog}
onDismiss={toggleHideDialog}
dialogContentProps={dialogContentProps}
modalProps={modalProps}
>
<DialogFooter>
<PrimaryButton onClick={toggleHideDialog} text="Send" />
<DefaultButton onClick={toggleHideDialog} text="Don't send" />
</DialogFooter>
</Dialog>
</>
);
};

Categories