How can I set Character Length in react-quill. In Docs it has been given that getLength() will return the length of the character in editor..
But I am Unable to figure out How to implement it.
My JSX
<ReactQuill theme='snow'
onKeyDown={this.checkCharacterCount}
value={this.state.text}
onChange={this.handleChange}
modules={modules}
formats={formats}
//style={{height:'460px'}}
/>
// OnChange Handler
handleChange = (value) => {
this.setState({ text: value })
}
//Max VAlue checker
checkCharacterCount = (event) => {
if (this.getLength().length > 280 && event.key !== 'Backspace') {
event.preventDefault();
}
}
How can I set Character Length in react-quill. In Docs it has been given that getLength() will return the length of the character in editor..
But I am Unable to figure out How to implement it.
My JSX
<ReactQuill theme='snow'
onKeyDown={this.checkCharacterCount}
value={this.state.text}
onChange={this.handleChange}
modules={modules}
formats={formats}
//style={{height:'460px'}}
/>
// OnChange Handler
handleChange = (value) => {
this.setState({ text: value })
}
//Max VAlue checker
checkCharacterCount = (event) => {
if (this.getLength().length > 280 && event.key !== 'Backspace') {
event.preventDefault();
}
}
The Above solution i found on GitHub . But its not working...
Share Improve this question edited Mar 29, 2019 at 12:55 Shubham Pratik asked Mar 24, 2019 at 7:28 Shubham PratikShubham Pratik 5423 gold badges7 silver badges19 bronze badges6 Answers
Reset to default 8I believe you are missing a reference to the ReactQuill
component itself. Without the reference you will not get access to any of its unprivileged methods (e.g. getLength()
). You could get a copy via your handleChange
method (https://github.com/zenoamaro/react-quill#props , i.e. 4th argument on the onChange prop) but I would recommend you simply add a separate ref prop to the ReactQuill
component and use that. See below an example re-written as a functional component (...since its 2020 already):
export const Editor = () => {
const [value, setValue] = React.useState(null);
const reactQuillRef = React.useRef();
const handleChange = (value) => setValue(value);
const checkCharacterCount = (event) => {
const unprivilegedEditor = reactQuillRef.current.unprivilegedEditor;
if (unprivilegedEditor.getLength() > 280 && event.key !== 'Backspace')
event.preventDefault();
};
return (
<ReactQuill theme='snow'
onKeyDown={checkCharacterCount}
ref={reactQuillRef}
value={this.state.text}
onChange={this.handleChange}
modules={modules}
formats={formats} />
)
}
Following should work:
class Editor extends React.Component {
constructor (props) {
super(props)
this.handleChange = this.handleChange.bind(this)
this.quillRef = null; // Quill instance
this.reactQuillRef = null;
this.state = {editorHtml : ''};
}
componentDidMount() {
this.attachQuillRefs()
}
componentDidUpdate() {
this.attachQuillRefs()
}
attachQuillRefs = () => {
if (typeof this.reactQuillRef.getEditor !== 'function') return;
this.quillRef = this.reactQuillRef.getEditor();
}
handleChange (html) {
var limit = 10;
var quill = this.quillRef;
quill.on('text-change', function (delta, old, source) {
if (quill.getLength() > limit) {
quill.deleteText(limit, quill.getLength());
}
});
this.setState({ editorHtml: html });
}
render () {
return <ReactQuill
ref={(el) => { this.reactQuillRef = el }}
theme="snow"
onChange={this.handleChange}
value={this.state.editorHtml}
/>
}
}
I've had the same problem! None of the solutions I've found were working for me but finally I managed to make it work.
I post my answer and maybe helps someone in a future!
This prevents the user to write more than 10 charcaters, in this case just for the example.
import ReactQuill, { Quill } from 'react-quill';
import 'react-quill/dist/quill.snow.css';
export Props from "./types";
const MAX_EDITOR_LENGTH = 10;
const modules = {
toolbar: {
container: [['bold', 'italic', 'underline'], [{ list: 'bullet' }]],
},
};
function App({control, editorName}: Props) {
Quill.register('modules/maxlength', function (quill: any, options: any) {
quill.on('text-change', function () {
const textLength = quill.getText().length;
if (textLength > options.maxLength) {
quill.deleteText(options.maxLength, textLength - options.maxLength);
}
});
});
return (
<Box>
<Controller
control={control}
name={editorName}
render={({ field }) => {
return (
<ReactQuill
{...field}
modules={{
...modules,
maxlength: { maxLength: MAX_EDITOR_LENGTH },
}}
/>
);
}}
/>
<FormHelperText>
<Box display="flex">
<span style={{ marginLeft: 'auto' }}>
{fieldName ? characterCount : 0}/{MAX_EDITOR_LENGTH}
</span>
</Box>
</FormHelperText>
</Box>
);
}
export default App;
I don't have a "proper" solution but more a workaround with tiny-emitter
that works also with copy-paste situations.
- First, we had to create a
CopyPaste
class extends fromclipboard
module. In that class, we put an emitter and pass thequill
instance into parameter.
const Emitter = require('tiny-emitter/instance');
const { Quill } =
typeof window === 'object' ? require('react-quill') : () => false;
const Delta = typeof window === 'object' ? require('quill-delta') : null;
const Clipboard =
typeof window === 'object' ? Quill.import('modules/clipboard') : null;
export class CopyPasteQuill extends Clipboard {
onPaste(e) {
e.preventDefault();
const range = this.quill.getSelection();
const text = e.clipboardData.getData('text/plain');
const delta = new Delta()
.retain(range.index)
.delete(range.length)
.insert(text);
const index = text.length + range.index;
const length = 0;
this.quill.updateContents(delta, 'silent');
this.quill.setSelection(index, length, 'silent');
Emitter.emit('reactQuill::paste', this.quill);
}
}
- Second, we have a normalize component
ReactQuillInput
to handle every cases . The only warning is linked to values that are passed to this component. You can't give himprops
directly, you have to store them in a state before.
import React, { useState } from 'react';
import ReactQuillInput from '@components/atoms/reactQuillInput/ReactQuillInput';
const component = props => {
const { text } = props;
const [quillValueState, setQuillValueState] = useState(
text ? text : ''
);
const onChange = html => {
setQuillValueState(html);
};
const reactQuillMaxLength = 300;
return (
<Container>
<ReactQuillInput
theme="bubble"
defaultValue={captionState}
value={captionState}
onChangeText={onChange}
placeholder={'Type your text ...'}
maxLength={reactQuillMaxLength}
/>
</Container>
)
}
export default component;
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import ReactQuill, { Quill } from 'react-quill';
import Emitter from 'tiny-emitter/instance';
import { CopyPasteQuill } from '@src/utils/copyPasteQuill';
import 'react-quill/dist/quill.snow.css';
require('medium-editor/dist/css/medium-editor.css');
require('../../../styles/content_editor.css');
require('../../../styles/quill.bubble.css');
const ReactQuillInput = props => {
const { onChangeText, maxLength } = props;
const [quillState, setQuillState] = useState({});
const [isMountedState, setIsMontedState] = useState(false);
if (typeof window === 'object' && isMountedState) {
Quill.register('modules/clipboard', CopyPasteQuill, true);
}
const setQuill = ref => {
if (!ref || ref === null) return;
if (typeof ref.getEditor !== 'function') return;
setQuillState(ref.getEditor());
setIsMontedState(true);
};
const handleChange = html => {
if (!isMountedState) return;
if (maxLength) {
quillState.on('text-change', () => {
if (quillState.getLength() > maxLength) {
quillState.deleteText(maxLength, quillState.getLength());
}
});
}
onChangeText(html);
};
Emitter.on('reactQuill::paste', _quill => {
if (maxLength) {
if (_quill.getLength() > maxLength) {
_quill.deleteText(maxLength, _quill.getLength());
}
}
});
return (
<ReactQuill
ref={el => {
setQuill(el);
}}
{...props}
onChange={handleChange}
/>
);
};
export default ReactQuillInput;
ReactQuillInput.propTypes = {
onChangeText: PropTypes.func,
maxLength: PropTypes.number,
};
ReactQuillInput.defaultProps = {
onChangeText: () => {},
};
I think we should set the text length inside the onChange event. Something like this:
const handleSetValue: ReactQuill.ReactQuillProps["onChange"] = (
_value,
_delta,
_source,
_editor
) => {
// _value is the html string
setValue(_editor.getContents());
onChange(_editor.getContents(), _value, _editor.getLength());
};
I Have the same Problem
found a solution
<ReactQuill
value={this.p.state._sentMessage.message}
onChange={this.handleChange} // Handle change
style={{ height: "150px", maxHeight: "200px", marginBottom: "50px" }}
className="my-5 ReactQuill"
modules={modules}
theme="snow"
/>
//
handleChange = (value: string | any[]) => {
const maxLength =300;
if (value.length <= maxLength) {
this.setState({ message: value });
} else {
this.setState({ message: value.slice(0, maxLength) });
}